是否需要使用Task.Run包装将在非GUI线程中继续的延续?

时间:2019-05-14 16:53:39

标签: c# async-await

这个问题是出于学习目的。我不确定要开发什么。

我有两个长时间运行的CPU绑定操作(JobAJobB)。两者都不与GUI交互。与Task.FromResult立即在await表达式中完成不同,我的Task.Run(()=>JobA()).ConfigureAwait(false)将控制权返回给调用者,并导致继续在非GUI线程中执行(由于ConfigureAwait(false))。

static void  JobA()
{
    for (int i = 0; i < int.MaxValue; i++) ;
}

static void JobB()
{
    for (int i = 0; i < int.MaxValue; i++) ;
}


private static async Task Async()
{            
    await Task.Run(()=>JobA()).ConfigureAwait(false);
    JobB();
    //await Task.Run(() => JobB());
}

private async void Button_Click(object sender, RoutedEventArgs e)
{  
    await Async();
}

问题

根据我的理解,不必像下面第二种情况那样用JobB来包装Task.Run,因为已经保证了延续可以在非GUI线程中运行。

private static async Task Async()
{            
    await Task.Run(()=>JobA()).ConfigureAwait(false);
    JobB();
}

private static async Task Async()
{            
    await Task.Run(()=>JobA()).ConfigureAwait(false);
    await Task.Run(() => JobB());
}

Exception在异步中的行为有些棘手,所以我问这个问题,因为我想知道发生异常时进行选区是否有风险。如果没有这种风险,我将删除此问题。

1 个答案:

答案 0 :(得分:5)

  

我的Task.Run(()=> JobA())。ConfigureAwait(false)将控制权返回给调用者并导致继续在非GUI线程中执行(因为ConfigureAwait(false))

真的吗?您确定吗?

await的一个有趣方面是,如果可能的话,它的行为是同步的。因此,如果在await检查任务时任务已经完成,则await将继续同步运行。在这种情况下,ConfigureAwait无效。

值得注意的是,当您使用不同的计算机使用不同的CPU速度,可用内存或缓存行为时,可能会发生这种情况。掌握了墨菲定律,您最终遇到了无法复制的生产问题,这总是很有趣。

所以,我从不依靠ConfigureAwait(false)来确保任何代码都在线程池线程上运行。这就是Task.Run的目的。对于您发布的简单案例,您可以在Task.Run内完成一项工作:await Task.Run(() => { JobA(); JobB(); });