使用未分配的局部变量的使用时异步/伺机 [英] Use of unassigned local variable when using async/await

查看:127
本文介绍了使用未分配的局部变量的使用时异步/伺机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这code,而不等待,编译:

This code, without await, compiles:

IEnumerable<PingResponse> pingResponses;
using (var prestoWcf = new PrestoWcf<IPingService>())
{
    pingResponses = prestoWcf.Service.GetAllForPingRequest(this.PingRequest);
}

foreach (PingResponse response in pingResponses) { // code here }

这code,用等待,不能编译:

This code, with await, does not compile:

IEnumerable<PingResponse> pingResponses;
await Task.Factory.StartNew(() =>
{
    using (var prestoWcf = new PrestoWcf<IPingService>())
    {
        pingResponses = prestoWcf.Service.GetAllForPingRequest(this.PingRequest);
    }
});

foreach (PingResponse response in pingResponses) { // code here }

该错误是:使用未分配的局部变量pingResponses

为什么要引入异步/的await导致此问题?

Why would introducing async/await cause this issue?

推荐答案

它不工作的原因是编译器无法知道提供给委托 StartNew 方法总是你的的foreach之前执行循环。你知道,我知道,但是编译器不能的证明的它给它的当前确定的转让规则。

The reason it doesn't work is that the compiler cannot know that the delegate provided to the StartNew method will always be executed before your foreach loop is. You know it, and I know it, but the compiler cannot prove it given it's current definite assignability rules.

虽然有几个变通办法只是欺骗编译器将让你做到这一点,最好的和最惯用的解决方案是有任务的返回结果的,而不是突变一个关闭了变量。你不依靠任务的副作用,而是结果本身的方式。这使得code更容易(使用它可以单独进行分析,而不是具有各相关的另一实施任务和$ C $三)推理,并确保不同的线程之间共享的存储器的正确同步(一个不平凡的任务)。

While there are several "workarounds" to just trick the compiler into letting you do this, the best and most idiomatic solution would be to have the task return a result rather than mutating a closed over variable. That way you're not relying on the task's side effects but rather the result itself. This makes the code easier to reason about (the task and the code using it can be analyzed separately, rather than having the implementation of each dependent on the other) and ensures proper synchronization of memory shared between different threads (a non-trivial task).

至于实际的code,它已经在提供 dcastro的回答

As for the actual code, it has already been provided in dcastro's answer:

IEnumerable<PingResponse> pingResponses = 
    await Task.Factory.StartNew(() =>
    {
        using (var prestoWcf = new PrestoWcf<IPingService>())
        {
            return prestoWcf.Service.GetAllForPingRequest(this.PingRequest);
        }
    });

更妙的是,按照<一个href=\"http://stackoverflow.com/questions/19731600/use-of-unassigned-local-variable-when-using-async-await/19731783#comment29316180_19731600\">SLack's建议您可以使用正确的是异步,而不是在一个线程池线程使用同步方法的方法。这样做使您能够利用操作系统来通知您一个网络请求的完成,而不会因为它坐在那里什么都不做生产浪费线程池的资源的能力。

Better still, as per SLack's suggestion you can use a method that is properly asynchronous, rather than using a synchronous method in a thread pool thread. Doing so allows you to leverage the operating systems ability to notify you of the completion of a network request without wasting the resources of the thread pool by having it sitting there doing nothing productive.

这篇关于使用未分配的局部变量的使用时异步/伺机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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