【发布时间】:2018-04-26 00:31:06
【问题描述】:
我有一个正在调用的方法,我想确保它在继续之前绝对完成。我也想知道它是否成功完成,所以我正在做以下事情:
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,这似乎可以按预期工作。但是,我很好奇async-await(或Task.Run)的复杂性似乎会导致无法保证out success 将被正确分配的情况。
感谢任何启发!
编辑:
为了添加更多上下文,以下代码块编译并执行良好。
void Caller() {
bool success;
Callee(out success);
if (success) {
// do something
}
}
void Callee();
这是因为out参数在传递之前不需要初始化。更多关于out:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
【问题讨论】:
-
导致错误的不是异步,而是您对成功的关闭;
Action t = () => { Bar(out success);};导致同样的错误 -
@ScubaSteve 这并不是问题所要问的。这更多地是关于为什么如果初始化发生在闭包中,变量仍然被认为是未初始化的。
-
我认为问题在于 Lambda,而不是异步。 Lambda 在创建变量时“捕获”变量。但是捕获是一种使用形式,你怎么能使用没有初始化的东西呢?尤其是在多任务处理(Lambda 的常见用法)中,捕获变得非常重要。
-
从编译器的角度来看,不能确定传递给 Task.Run 的委托实际上会在方法返回之前被 Task.Run 调用。是的,我们知道它会,因为我们知道 Task.Run 应该如何工作,并且我们假设它没有任何错误,但是如果 MSFT 错误地实现了它,以至于在一些罕见或奇怪的情况下 Task.Run 实际上并没有运行提供的委托并返回而不抛出任何异常。如果这是可能的(确实如此),那么您的代码可能会在未成功初始化的情况下到达 if 语句。
标签: c# async-await task out