Mat*_*ang 4 .net c# task async-await c#-5.0
我从一个沉重的java背景中对C#有点新,并且仍在试图弄清楚await和async是如何工作的,这里有什么令我困惑的事情:
假设我有一个这样的函数(下面的Hackish代码仅用于实验):
public static bool CheckInternetConnection()
{
Task<bool> result = CheckInternetConnectionAsync();
return result.Result;
}
public async static Task<bool> CheckInternetConnectionAsync()
{
if (NetworkInterface.GetIsNetworkAvailable())
{
SomeClass details = await ReturnARunningTask();
return details.IsSuccessful;
}
return false;
}
public Task<SomeClass> ReturnARunningTask()
{
return Task.Run(() => checkInternet());
}
Run Code Online (Sandbox Code Playgroud)
在主执行线程中,如果我调用它:
CheckInternetConnection();
Run Code Online (Sandbox Code Playgroud)
它将无限期地阻塞,我的假设是控制在"await"关键字上留下CheckInternetConnectionAsync()并阻止".Result".等待恢复时,主线程已被阻止并保持阻塞状态
我假设的原因是我可以看到任务完成并返回,但是await之后的代码永远不会被执行
但是,如果我这样做:
bool result = Task.Run(() => CheckInternetConnection()).Result;
Run Code Online (Sandbox Code Playgroud)
然后执行await语句后的代码,主线程继续
我的期望是它也会阻塞,因为主线程将在中间任务上被阻塞.中间任务将被阻止在.Result上
那么......有什么不同?在这种情况下,await执行后的代码是什么?
i3a*_*non 14
在UI环境中,您有一个特殊的单线程SynchronizationContext,可以在UI线程上运行所有内容.在您await执行任务时捕获该上下文,并且当任务完成时,该方法将在该捕获的上下文上恢复(这可以使用ConfigureAwait以下命令进行配置:
SomeClass details = await ReturnARunningTask().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
在您Task.Result未完成的任务中使用该属性的情况下,您同步阻止UI线程,因此当CheckInternetConnectionAsync尝试SynchronizationContext在ReturnARunningTask完成后继续尝试时它不能.UI线程被阻塞等待CheckInternetConnectionAsync任务,而该任务又等待UI线程,因此死锁(无限期阻塞).
使用时的区别Task.Run(() => CheckInternetConnection()).Result;在于使用Task.Run卸载工作要在ThreadPool线程上完成.这些线程没有SynchronizationContext,所以当UI线程被阻塞时.Result,任务就可以完成,因为它不需要UI线程这样做.
不鼓励阻止异步操作(同步结束async),因为它会阻止线程并使应用程序响应性和可伸缩性降低,并且可能导致死锁.您应该使用async-await所有的方式.
注意:async您应该使同步版本保持同步,而不是进行"同步",如果您需要async将CPU密集型工作卸载到其他线程的版本,请使用Task.Run:
public static bool CheckInternetConnection()
{
return checkInternet().IsSuccessful;
}
public async static Task<bool> CheckInternetConnectionAsync()
{
if (NetworkInterface.GetIsNetworkAvailable())
{
return await Task.Run(() => CheckInternetConnection());
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1646 次 |
| 最近记录: |