是否有必要包裹将使用Task.run中的非GUI线程的延续



这个问题是出于学习目的。我不肯定地开发任何东西。

我有两个长期运行的CPU结合操作(JobAJobB(。两者都不与GUI互动。与立即在等待表达式完成的Task.FromResult不同,我的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();
}

问题

在我的理解中,将JobBTask.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异步中的行为有点棘手,所以我问这个问题,因为我想知道当异常发生时是否有风险。如果没有这种风险,我将删除这个问题。

我的task.run(((=> joba(((。configureawait(false(将返回控制器,并导致延续在非GUI线程中执行(因为configureawait(false((

真的吗?您确定吗?

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

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

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

最新更新