【问题标题】:Returning from async method before locals are assigned在分配本地人之前从异步方法返回
【发布时间】:2015-12-07 17:13:41
【问题描述】:

此异步方法产生两个 CS0165 错误 - 使用未分配的局部变量。

public async Task<Tuple<bool, string>> DoWorkAsync(object[] objs)
{
    string msg;
    bool result;
    await Task.Run(() => result = _foo.DoWork(objs, out msg));
    return new Tuple<bool, string>(result, msg);
}

最初我想问为什么,但现在我很确定这是因为本地任务中可能会引发异常。

请参阅下面魔术师 Jon Skeet 的评论:编译器不知道 Task.Run 在做什么,也无法推断将分配本地人。

所以现在我要问:实现这一点的最佳方法是什么?为本地分配默认值,为任务创建本地并检查任务。返回前是否出现错误?

我一般应该传播异常吗?我想这可能是一个无法回答的问题,具体取决于上下文。

【问题讨论】:

  • 对于初学者,不要使用Task.Run 来伪造异步。
  • 这不是因为可能引发异常,而是因为 C# 编译器不知道 Task.Run 的作用。就它而言,这只是一种任意方法。
  • 这解释了为什么不应该为同步方法公开异步包装器:blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx
  • @Michael:不,它不能。想象一下,你在那里打电话给Foo.Bar 而不是Task.Run - 你认为这应该改变吗?想象一下Foo.Bar 只是一个返回Task&lt;int&gt; 的方法,从未执行过委托。

标签: c# async-await


【解决方案1】:

从您的Task.Run 返回Tuple,如下所示:

public Task<Tuple<bool, string>> DoWorkAsync(object[] objs)
{
    return Task.Run(() => 
    {
        string msg;
        var result = _foo.DoWork(objs, out msg);
        return new Tuple<bool, string>(result, msg);
    });
}

现在您无需担心未初始化的局部变量。

【讨论】:

  • 哦。呃。这样看起来干净多了。
  • 但是使用此解决方案,您的方法不再是async。 (虽然你可能不需要它,因为你不再await)。
  • @RenéVogt 它不需要从头开始。但它仍然可以使用 async 和 await 而不是简单的 return。
  • @RenéVogt async 关键字变得多余,因为我们可以直接从 Task.Run 返回 Task。如果您希望您仍然可以输入 async/await 关键字,但您并没有真正获得收益,只是性能略有下降。
  • 知道了,更新我的答案后,我意识到它几乎完全是你的,所以我删除了我的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-25
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 2015-06-13
相关资源
最近更新 更多