【发布时间】:2018-04-08 13:42:25
【问题描述】:
我发现async 方法的行为非常令人困惑。考虑以下控制台应用:
private static int _i = 0;
private static Task<int> _calculateTask = Task.FromResult(0);
private static int _lastResult = 0;
static void Main(string[] args)
{
while (true)
{
Console.WriteLine(Calculate());
}
}
private static int Calculate()
{
if (!_calculateTask.IsCompleted)
{
return _lastResult;
}
_lastResult = _calculateTask.Result;
_calculateTask = CalculateNextAsync();
return _lastResult;
}
private static async Task<int> CalculateNextAsync()
{
return await Task.Run(() =>
{
Thread.Sleep(2000);
return ++_i;
});
}
不出所料,它启动后,首先打印出一堆0,然后是一个,二等。
相比之下,请考虑以下 UWP 应用 sn-p:
private static int _i = 0;
private static Task<int> _calculateTask = Task.FromResult(0);
private static int _lastResult = 0;
public int Calculate()
{
if (!_calculateTask.IsCompleted)
{
return _lastResult;
}
_lastResult = _calculateTask.Result;
_calculateTask = CalculateNextAsync();
return _lastResult;
}
private static async Task<int> CalculateNextAsync()
{
return await Task.Run( async() =>
{
await Task.Delay(2000);
return ++_i;
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
while( true)
{
Debug.WriteLine(Calculate());
}
}
虽然这两个只有一个小细节不同,但 UWP sn-p 只是保持打印出 0,if 语句中的任务状态只是保持Waitingforactivation。此外,可以通过从CalculateNextAsync 中删除async 和await 来解决此问题:
private static Task<int> CalculateNextAsync()
{
return Task.Run(async () =>
{
await Task.Delay(2000);
return ++_i;
});
}
现在一切都与控制台应用程序中的一样。
有人可以解释为什么控制台中的行为与 UWP 应用程序不同的原因吗?为什么在 UWP 应用的情况下任务保持为c?
更新
我又回到了这个问题,但发现了一个最初接受的答案没有涵盖的问题 - UWP 上的代码从未到达.Result,它只是不断检查@ 987654332@ 返回false,因此返回_lastResult。是什么让 Task 在本应完成时具有 AwaitingActivation 状态?
解决方案
我发现原因是主动等待 while 循环阻止了 await 延续再次占用 UI 线程,从而导致类似“死锁”的情况。
【问题讨论】:
标签: c# asynchronous async-await task task-parallel-library