我有一个异步调用,我将其包装在Task中。运行以在另一个线程中运行它。组织分配和所有后续代码是否会一直暂停,直到返回并获得结果?还是会继续,甚至在到达foreach后有时会生成空引用异常?在我的测试中,它从不会抛出错误,但是也许我很幸运。
IDictionary<string, organization> organizations = Task.Run(() => this.GetOrganizationsAsync()).Result;
...lines of code
foreach (var organization in organizations)
{
答案 0 :(得分:3)
Remarks section of the documentation for Task.Result
说:
访问属性的get访问器会阻塞调用线程,直到异步操作完成为止;等效于调用Wait方法。
是的,直到GetOrganizationsAsync()
完成,它才能继续进行。但是有两件事:
没有理由使用Task.Run
。当您希望某物移动到另一个线程时可以使用它,以便当前线程可以继续执行其他操作。但是,然后您将阻塞当前线程,直到它完成为止。因此Task.Run
只是无缘无故地增加了开销。
阻塞异步操作也会导致死锁问题:Don't Block on Async Code
有什么理由不能仅仅使方法async
并使用await GetOrganizationsAsync()
?这是更可取的,因为您不会阻塞任何线程。
Microsoft在Asynchronous programming with async and await上有一系列写得很好的文章,值得阅读。
答案 1 :(得分:0)
调用.Result是一个坏主意,因为它有时会导致您的代码被锁定-我建议您做一些阅读以说服自己。
最好的方法是在GetOrganizationsAsync上调用await,并使执行该方法的方法异步。这可能意味着asyc方法开始在整个代码中传播,但这就是cookie崩溃的方式。有很多方法可以避免这样做,而且我已经看到它是在生产代码中编写的,这些代码主要是有效,但是我不建议这样做。
有关此主题的更多阅读内容: Is Task.Result the same as .GetAwaiter.GetResult()?