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

时间:2019-06-05 04:09:40

标签: c# func

我有一种方法来显示带有参数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;
    });
}

3 个答案:

答案 0 :(得分:1)

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

为此,您必须将委托定义为Func<Task<int>>,因为所有等待的方法都必须返回某种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;
    });
}

但是更简单的方法是使用close动作处理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);
}

答案 1 :(得分:0)

要考虑的一个选项是添加一个新方法,当备份为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

答案 2 :(得分:0)

谢谢大家,现在我有一个解决方案。只需将backup.sqlBackupAsync更改为backup.sqlBackup,然后在ShowLoading方法中,在DoWork中创建一个新的BackgroudWorker,然后添加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();
    }