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语句。