C# 使用“时不清楚编译器错误”;“出去”;在C中的异步等待块中#

C# 使用“时不清楚编译器错误”;“出去”;在C中的异步等待块中#,c#,async-await,task,out,C#,Async Await,Task,Out,我有一个正在调用的方法,我希望在继续之前确保它完全完成。我还想知道它是否成功完成,因此我正在做以下工作: async void Foo() { bool success; // stuff await Task.Run( () => Bar(out success) ); if (!success) { // this is the line causing the compiler-error // handle } // other

我有一个正在调用的方法,我希望在继续之前确保它完全完成。我还想知道它是否成功完成,因此我正在做以下工作:

async void Foo() {
  bool success;

  // stuff

  await Task.Run(
    () => Bar(out success)
  );

  if (!success) { // this is the line causing the compiler-error
    // handle
  }

  // other stuff
}

void Bar(out bool success);
但我犯了个错误

CS0165未分配局部变量“成功”的使用

这没什么大不了的,因为我可以很可爱地初始化
success=false
,并将其作为
ref
传递,而不是
out
,这似乎可以按预期工作。然而,我很好奇
异步等待
(或
任务.运行
)的复杂性是什么,它们似乎导致了一种情况,即不能保证
输出成功

任何启示都是值得赞赏的

编辑:

为了添加更多的上下文,下面的块编译并执行得很好

void Caller() {
  bool success;
  Callee(out success);
  if (success) {
    // do something
  }
}

void Callee();

这是因为
out
参数在传递之前不需要初始化。有关
out

的详细信息,请考虑
任务的以下可能(尽管完全不正确)实现。运行

public class Task
{
    public static Task Run(Action action)
    {
        return Task.Delay(500);
    }
    //...
}
现在想想有问题的代码。通过执行
Task.Run
,会调用
Bar
方法吗?否。因此,
success
将永远不会初始化,并尝试访问未初始化的变量


编译器不知道
任务的实际实现。运行
或它将执行什么操作。它不能假设它没有像上面那样实现,因此可以使用未初始化的变量。

考虑以下可能(尽管完全不正确)的
任务实现。运行

public class Task
{
    public static Task Run(Action action)
    {
        return Task.Delay(500);
    }
    //...
}
现在想想有问题的代码。通过执行
Task.Run
,会调用
Bar
方法吗?否。因此,
success
将永远不会初始化,并尝试访问未初始化的变量


编译器不知道
任务的实际实现。运行
或它将执行什么操作。它不能假设它没有像我上面所说的那样被实现,因此一个未初始化的变量是可能的。

导致错误的不是异步的,而是你有一个成功的闭包<代码>动作t=()=>{Bar(out成功);}导致相同的错误error@ScubaSteve这不是真正的问题所在。这更多的是关于如果初始化发生在闭包中,为什么变量仍然被认为是单元化的。我认为问题在于Lambda,而不是异步。Lambdas“捕获”变量它们被创建的时刻。但是捕获是一种使用形式,你怎么能使用没有初始化的东西呢?特别是在多任务处理(Lambdas的一种常见用法)中,捕获变得非常重要。从编译器的角度来看,无法确定传递给Task.Run的委托实际上将由Task.Run调用,否则方法将返回。是的,我们知道会,因为我们知道Task.Run应该如何工作,并且我们假设它没有任何bug,但是如果MSFT错误地实现了它,以至于在某些罕见或奇怪的情况下Task.Run实际上不会运行提供的委托,并且返回时不会抛出任何异常,该怎么办。如果这是可能的(而且确实如此),那么代码就有可能在没有成功初始化的情况下到达If语句<代码>动作t=()=>{Bar(out成功);}导致相同的错误error@ScubaSteve这不是真正的问题所在。这更多的是关于如果初始化发生在闭包中,为什么变量仍然被认为是单元化的。我认为问题在于Lambda,而不是异步。Lambdas“捕获”变量它们被创建的时刻。但是捕获是一种使用形式,你怎么能使用没有初始化的东西呢?特别是在多任务处理(Lambdas的一种常见用法)中,捕获变得非常重要。从编译器的角度来看,无法确定传递给Task.Run的委托实际上将由Task.Run调用,否则方法将返回。是的,我们知道会,因为我们知道Task.Run应该如何工作,并且我们假设它没有任何bug,但是如果MSFT错误地实现了它,以至于在某些罕见或奇怪的情况下Task.Run实际上不会运行提供的委托,并且返回时不会抛出任何异常,该怎么办。如果这是可能的(而且确实如此),那么代码就有可能在没有成功初始化的情况下到达If语句。