如何等待 Func<T>().Invoke

How to wait Func<T>().Invoke

我有一个方法来显示带有参数 Func<T> 的加载表单,在该方法中我使用 func.Invoke(); this.Close();

但在这个演员表中 this.Close();不等待 func.Invoke 完成。

请帮帮我。

private void ShowLoading<T>(Func<T> func)
{
    func.Invoke();

    this.Close();
}

private void Button1_Click_1(object sender, EventArgs e)
{
    ShowLoading(() =>
    {
        Server server = new Server(new ServerConnection(".\sqlexpress", "sa", "underadmin"));
        Backup backup = new Backup() { Action = BackupActionType.Database, Database = "TestMedia" };
        backup.Devices.AddDevice(@"D:\BACKUP\TestMedia.bak", DeviceType.File);
        backup.Initialize = true;
        backup.PercentComplete += Backup_PercentComplete;
        backup.SqlBackupAsync(server);
        return 0;
    });
}

使您的点击处理程序异步并在委托中设置 TaskCompletionSource。

为此,您必须将委托定义为 Func<Task<int>>,因为所有可等待的方法都必须 return 某种 Task<>

private async Task ShowLoading(Func<Task<int>> func)
{
    await func.Invoke();

    this.Close();
}

private async void Button1_Click_1(object sender, EventArgs e)
{
    await ShowLoading( () =>
    {
        var source = new TaskCompletionSource<int>();
        Server server = new Server(new ServerConnection(".\sqlexpress", "sa", "underadmin"));
        Backup backup = new Backup() { Action = BackupActionType.Database, Database = "TestMedia" };
        backup.Devices.AddDevice(@"D:\BACKUP\TestMedia.bak", DeviceType.File);
        backup.Initialize = true;
        backup.PercentComplete += Backup_PercentComplete;
        backup.Complete += (s,e) => { source.SetResult(0); };
        backup.SqlBackupAsync(server);
        return source.Task;
    });
}

但更简单的方法是使用关闭操作处理 Complete 事件。

private void Button1_Click_1(object sender, EventArgs e)
{
    Server server = new Server(new ServerConnection(".\sqlexpress", "sa", "underadmin"));
    Backup backup = new Backup() { Action = BackupActionType.Database, Database = "TestMedia" };
    backup.Devices.AddDevice(@"D:\BACKUP\TestMedia.bak", DeviceType.File);
    backup.Initialize = true;
    backup.PercentComplete += Backup_PercentComplete;
    backup.Complete += (o,e) => { this.Close(); };
    backup.SqlBackupAsync(server);
}

要考虑的一个选项是添加一个新方法,该方法在备份 completed 时调用 - 该方法 有责任调用 this.Close.

您使用与 PercentComplete:

类似的方式来执行此操作
backup.PercentComplete += Backup_PercentComplete;

所以会是:

backup.Complete += Backup_Complete; // or whatever you want the method to be called:

Backup_Complete 会有 this.Close; 行代码,而不是 ShowLoading.

谢谢大家,现在我有办法了。只需将 backup.sqlBackupAsync 更改为 backup.sqlBackup 然后我在方法 ShowLoading 中创建一个新的 BackgroudWorker 在 DoWork 我添加 fucn.Invoke();然后在 DoWorkCompleted 中调用 this.Close();工作正常:)

private void Button1_Click_1(object sender, EventArgs e)
    {
        ShowLoading(() =>
        {
            Server server = new Server(new ServerConnection(".\sqlexpress", "sa", "underadmin"));
            Backup backup = new Backup() { Action = BackupActionType.Database, Database = "TestMedia" };
            backup.Devices.AddDevice(@"D:\BACKUP\TestMedia.bak", DeviceType.File);
            backup.Initialize = true;
            backup.PercentComplete += (s, ev) => lblPercent.Text = ev.Percent.ToString();
            backup.SqlBackup(server);
            return 0;
        });
    }

    private void ShowLoading<T>(Func<T> func)
    {
        var bgk = new BackgroundWorker();
        bgk.DoWork += (s, e) => func.Invoke();
        bgk.RunWorkerCompleted += (s, e) => this.Close();
        bgk.RunWorkerAsync();
    }