繁体   English   中英

C#等待Task.Run不等待

[英]C# await Task.Run is not awaited

我有一些长期运行的后台计算任务

private async void StartButton_onClick(object sender, RoutedEventArgs e)
{
    cts = new CancellationTokenSource();
    var task = Task.Run(() => Calculate(cts.Token));
    tasks.Add(task);
    await task;
    tasks.Remove(task);
    cts = null;
}

当用户单击“ Cancel按钮时,该任务可以被取消;当用户调用其他活动时,该任务应该被自动取消,例如,按“ Change按钮以打开一个对话框来更改计算参数。

为了避免两次为两次写入取消代码,我将其移至单独的方法

public async void CancelAsync()
{
    if (cts != null && !cts.IsCancellationRequested)
    {
        cts.Cancel();
        await Task.WhenAll(tasks);
    }
}

并从按钮click事件中调用它

private async void CancelButton_onClick(object sender, RoutedEventArgs e)
{
    await Task.Run(() => CancelAsync());
}

private async void ChangeButton_onClick(object sender, RoutedEventArgs e)
{
    await Task.Run(() => CancelAsync());
    OpenDialog();
}

问题在于, CancelAsync()运行到CancelAsync() 之前 ,将调用OpenDialog()方法。

请问我在这里错了什么?

由于您是从既未异步也未等待的lambda调用CancelAsync()的,因此该lambda将在CancelAsync()方法返回之前完成。 为了使其按预期工作,请使用

public async Task CancelAsync()
{
    if (cts != null && !cts.IsCancellationRequested)
    {
        cts.Cancel();
        await Task.WhenAll(tasks);
    }
}

await CancelAsync();

问题是使用Task.Run ,它旨在在线程池上运行一些同步代码,并让您等待其结果。 但是,您将异步代码传递给Task.Run ,就好像它是同步代码一样,因此Task.Run认为工作是在CancelAsync()返回任务时完成的,而不是在完成任务时完成的。

尝试以下方法:

private async void ChangeButton_onClick(object sender, RoutedEventArgs e)
{
    await CancelAsync();
    OpenDialog();
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM