- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我发现 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,然后是 ones,twos 等等。
相比之下,请考虑以下 UWP 应用代码段:
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 片段只是不断打印出 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
,它只是不断检查返回 false
的 IsCompleted
,因此返回 _lastResult
。什么使 Task
在本应完成时具有 AwaitingActivation
状态?
我发现原因是事件等待 while
循环阻止 await
继续再次占用 UI 线程,因此导致类似“死锁”情况。
最佳答案
根据 UWP 应用程序中的代码,无需保留 _calculateTask
。只需等待
任务即可。
这是更新后的代码
private static int _i = 0;
private static int _lastResult = 0;
public async Task<int> Calculate() {
_lastResult = await CalculateNextAsync();
return _lastResult;
}
//No need to wrap the code in a Task.Run. Just await the async code
private static async Task<int> CalculateNextAsync()
await Task.Delay(2000);
return ++_i;
}
//Event Handlers allow for async void
private async void Button_Click(object sender, RoutedEventArgs e) {
while( true) {
var result = await Calculate();
Debug.WriteLine(result.ToString());
}
}
您在 UWP 应用程序中混合了异步/等待和阻塞调用,例如 .Result
,因为它的一个 block SynchronizationContext 而导致死锁。控制台应用程序是该规则的一个异常(exception),这就是它在那里工作而不在 UWP 应用程序中工作的原因。
The root cause of this deadlock is due to the way await handlescontexts. By default, when an incomplete Task is awaited, the current“context” is captured and used to resume the method when the Taskcompletes. This “context” is the current SynchronizationContext unlessit’s null, in which case it’s the current TaskScheduler. GUI andASP.NET applications have a SynchronizationContext that permits onlyone chunk of code to run at a time. When the await completes, itattempts to execute the remainder of the async method within thecaptured context. But that context already has a thread in it, whichis (synchronously) waiting for the async method to complete. They’reeach waiting for the other, causing a deadlock.
Note that console applications don’t cause this deadlock. They have athread pool SynchronizationContext instead of a one-chunk-at-a-timeSynchronizationContext, so when the await completes, it schedules theremainder of the async method on a thread pool thread. The method isable to complete, which completes its returned task, and there’s nodeadlock. This difference in behavior can be confusing whenprogrammers write a test console program, observe the partially asynccode work as expected, and then move the same code into a GUI orASP.NET application, where it deadlocks.
关于c# - 异步任务方法 WaitingForActivation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46966772/
我试图找出 async 和 await 关键字的全部内容,但是输出不是我所期望的。 控制台应用如下: class Program { static void Main(string[] arg
我有一个共享 BlockingCollection 的消费者/生产者设置。 public void StartConsumer(CancellationToken cancellationToken)
我有以下功能: async public Task checkNetwork (RestClient _client, ConnectivityManager conn) {
我发现 async 方法有一个非常令人困惑的行为。考虑以下控制台应用程序: private static int _i = 0; private static Task _calculateTask
我试图找出 async 和 await 关键字的全部内容,但是输出不是我所期望的。 控制台应用如下: class Program { static void Main(string[] arg
public void DoStuff() { // I want to be able to call the method DoAsynckStuff and wait for the r
我只有一种 Api Request 方法如下 private async Task getSiteAsync(string siteId) { Site site = null; va
我正在尝试在 VS2012 框架 4.5 的表单上使用异步和等待命令。我的异步方法 SlowMethodAsync 不返回任何内容。请注意,此代码在控制台应用程序中运行良好。 private void
我正在用下面的方式启动 wpf 任务 var newTask = Task.Factory.StartNew(() => { fcStartSubPageCrawl(srMainSiteURL, sr
我正在使用 TaskFactory 使用以下代码启动新任务。 var task = Task.Factory.StartNew(async () => { await Task.Run(()
我已经下载了 EF6 (为了使用 async) 所以我写了这个简单的方法: public async Task> MyasyncMethod() { var loc
我正在尝试发送 url 请求并异步获取响应,但是当我将 .fromAsync 方法与 .ContinueWith 方法一起使用时,任务状态永远不会从 WaitingForActivation 更改为运
我是 HttpClient 的新手。我下面的代码总是在状态中显示“WaitingForActivation”。请帮忙 private static async Task MakeCall() {
我是 C# 中的任务的新手。我正在尝试按照有关将 arm 模板部署到 azure 以启动虚拟机的示例进行操作: https://azure.microsoft.com/en-us/documentat
给定以下代码: Dim t As Date = Now Dim e As New AsynchronousExecutionEventArgs
我是 AWS 的新手,正在尝试设置我的系统以在预订后向最终用户发送 SMS 作为确认消息。 到目前为止,我在下面做了: AmazonSimpleNotificationServiceClient sm
我正在尝试使用 Azure 中的托管身份连接到我的 Key Vault。为此,我在 appsettings.json 的 KeyVault 下的 Vault 下添加了一个带有 Key Vault 名称
我是一名优秀的程序员,十分优秀!