同时采用异步等待死锁 [英] Deadlock while using async await

查看:267
本文介绍了同时采用异步等待死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解等待和异步。
它工作得很好。但现在我已经陷入僵局。我叫ConfigureAwait以虚假的,像这样的文章:<一href=\"http://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-$p$pvent-deadlocks-in-async-$c$c/\" rel=\"nofollow\">http://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-$p$pvent-deadlocks-in-async-$c$c/
但我的code仍然阻挡。
这里有一个小片段我的code的:

 私人无效的button1_Click(对象发件人,EventArgs的发送)
    {
        VAR的结果= HeavyWorkAsync()结果。
        richTextBox1.AppendText(结果);
    }    私人字符串HeavyWork()
    {
        对于(VAR指数= 0;指数 - LT; 1000;指数++)
        {
            Task.Delay(10).Wait();
        }        返回完了;
    }    私人异步任务&LT;串GT; HeavyWorkAsync()
    {
        VAR任务等待=&Task.Factory.StartNew LT;串&GT;(HeavyWork).ConfigureAwait(假);
        返回任务;
    }


解决方案

什么是堵是不是任务本身,它调用结果。 A 工作重新presents异步操作,而是调用其结果属性,或调用等待()将阻止当前线程,直到这个方法返回。而且在很多情况下,就会造成死锁因为任务是不能够与它的调用线程阻塞完成!

要prevent的是,链任务异步,使用异步等待

 专用异步无效的button1_Click(对象发件人,EventArgs的发送)
{
    VAR的结果=等待HeavyWorkAsync(); //&LT; ===等待
    richTextBox1.AppendText(结果);
}

此外, Task.Delay(10).Wait(); 完全违背了使用摆在首位任务的prupose:这将阻止当前线程。如果是这样的真正你想做的事(和它的pretty不太可能),调用 Thread.sleep代码(10); 相反,它将让你的意图更加清晰,你将有较少的箍通过跳跃。或者更好,使用等待Task.Delay(10); 在异步方法

关于 ConfigureAwait

到底是什么 ConfigureAwait(假)吗?

这消除了对任务的延续,在相同的上下文中任务的调用者运行的义务。在大多数情况下,这意味着延续不再保证在同一个环境中运行。所以,如果我有一个方法萨德确实美孚(),等了一小会酒吧()像这样的:

 异步任务DoStufAsync()
{
    美孚();
    等待Task.Delay(10);
    酒吧(); //在相同的上下文中富的run()
}

我保证律师将在同一环境中运行。如果我有 ConfigureAwait(假),它不再是这样了。

 异步任务DoStufAsync()
{
    美孚();
    等待Task.Delay(10).ConfigureAwait(假);
    酒吧(); //可以在另一个线程为Foo)运行(
}

当你使用 ConfigureAwait(假),你告诉你的程序,你不介意有关上下文。它可以解决一些问题,死锁,但通常不是正确的解决方案。正确的解决方案是最有可能永远等待任务阻塞道路,是异步的,所有的方式。

I'm trying to understand await and async. It works very well. But now I've a deadlock. I've called ConfigureAwait with false, like in this article: http://blog.ciber.no/2014/05/19/using-task-configureawaitfalse-to-prevent-deadlocks-in-async-code/ But my code is still blocking. Here's a little snippet out of my code:

 private void button1_Click(object sender, EventArgs e)
    {
        var result = HeavyWorkAsync().Result;
        richTextBox1.AppendText(result);
    }

    private string HeavyWork()
    {
        for (var index = 0; index < 1000; index++)
        {
            Task.Delay(10).Wait();
        }

        return "finished";
    }

    private async Task<string> HeavyWorkAsync()
    {
        var task = await Task.Factory.StartNew<string>(HeavyWork).ConfigureAwait(false);
        return task;
    }

解决方案

What's blocking is not the task itself, it's the call to Result. A Task represents an asynchronous operation, but calling its Result property, or calling Wait() will block the current thread until the method returns. And in a lot of cases, it will cause a deadlock because the task is not able to complete with it's calling thread blocked!

To prevent that, chain the tasks asynchronously, using async and await

private async void button1_Click(object sender, EventArgs e)
{
    var result = await HeavyWorkAsync(); // <=== await
    richTextBox1.AppendText(result);
}

Also, Task.Delay(10).Wait(); completely defeats the prupose of using tasks in the first place: that will block the current thread. If that's really what you want to do (and it's pretty unlikely), call Thread.Sleep(10);instead, it will make your intent much clearer, and you will have less hoops to jump through. Or better, use await Task.Delay(10);in an async method.

About ConfigureAwait

What exactly does ConfigureAwait(false) do?

It removes the obligation for the continuation of the task to run in the same context as the caller of the task. In most cases that means that the continuation is no longer guaranteed to run on the same context. So if I have a method thad does Foo(), waits a little then Bar() like this one:

async Task DoStufAsync()
{
    Foo();
    await Task.Delay(10);
    Bar(); // run in the same context as Foo()
}

I'm guaranteed Bar will run in the same context. If I had ConfigureAwait(false), it's no longer the case

async Task DoStufAsync()
{
    Foo();
    await Task.Delay(10).ConfigureAwait(false);
    Bar(); // can run on another thread as Foo()
}

When you're using ConfigureAwait(false), you tell your program you dont mind about the context. It can solve some deadlocking problems, but isn't usually the right solution. The right solution is most likely never to wait for tasks in a blocking way, and being asynchronous all the way.

这篇关于同时采用异步等待死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆