为什么此异步 *** 作挂起?

为什么此异步 *** 作挂起?,第1张

为什么此异步 *** 作挂起?

是的,这是一个僵局。这是TPL的常见错误,所以不要感到难过。

当您编写

awaitfoo
时,默认情况下,运行时将在该方法开始的同一SynchronizationContext上调度函数的继续。用英语来说,假设您是
ExecuteAsync
从UI线程调用的。您的查询在线程池线程上运行(因为您调用了
Task.Run
),但是随后等待结果。这意味着运行时将安排您的“
return result;
”行在UI线程上运行,而不是将其安排回线程池。

那么,这种僵局又如何呢?假设您只有以下代码:

var task = dataSource.ExecuteAsync(_ => 42);var result = task.Result;

因此,第一行开始了异步工作。然后第二行 阻塞UI线程
。因此,当运行时想要在UI线程上重新运行“返回结果”行时,它必须等到

Result
完成后才能执行。但是,当然,要等到返回发生后才能给出结果。僵局。

这说明了使用TPL的关键规则:在

.Result
UI线程(或其他一些花哨的同步上下文)上使用时,必须小心确保不会将Task所依赖的任何项目安排到UI线程中。否则邪恶就会发生。

所以你会怎么做?选项#1随处可见,但是正如您所说的,这已经不是一个选择。您可以使用的第二种选择是停止使用await。您可以将两个函数重写为:

public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function){    string connectionString = dataSource.ConnectionString;    // Start the SQL and pass back to the caller until finished    return Task.Run(        () =>        { // Copy the SQL connection so that we don't get two commands running at the same time on the same open connection using (var ds = new OurDBConn(connectionString)) {     return function(ds); }        });}public static Task<ResultClass> GetTotalAsync( ... ){    return this.DBConnection.ExecuteAsync<ResultClass>(        ds => ds.Execute("select slow running data into result"));}

有什么不同?现在没有等待的地方,因此没有任何隐式调度到UI线程的事情。对于像这样的简单方法,它们只有一个返回值,所以没有必要做一个“

var result= await...; return result
”模式。只需删除异步修改器,然后直接传递任务对象即可。如果没有其他问题,那么开销会更少。

选项#3指定您不希望将等待调度回UI线程,而只是调度到线程池。您可以使用

ConfigureAwait
方法执行此 *** 作,如下所示:

public static async Task<ResultClass> GetTotalAsync( ... ){    var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(        ds => return ds.Execute("select slow running data into result");    return await resultTask.ConfigureAwait(false);}

通常,等待任务将安排在UI线程上;等待的结果

ContinueAwait
将忽略您所处的任何上下文,并始终计划到线程池中。这样做的缺点是您必须在.Result所依赖的所有函数中的
任何地方 都撒上它,因为任何遗漏都
.ConfigureAwait
可能导致另一个死锁。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5499124.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存