正如有人在评论中所说,你不能等待而不阻塞。
但是,您可以等待而无需等待。
这完全取决于你所说的“等待”这个词到底是什么意思。
通常,您只希望在满足一组条件时执行一段代码。但这并不意味着您必须阻止任何事情。
考虑一下:
bool condition1 = false;
bool condition2 = false;
bool condition3 = false;
aFunction1() { condition1 = true; }
aFunction2() { condition2 = true; }
aFunction3() { condition3 = true; }
whenJobHasBeenCompleted() { console.writeline("all three were done!"); }
// and I'd like to have it automagically called..:
if(cond1 && cond2 && cond3) whenJobHasBeenCompleted();
因此,显然,我希望在调用所有先前函数后执行最后一个函数 - 但我并不关心谁调用了它们以及以什么顺序调用它们。
有很多工具*),但考虑最简单和最明显的:普通的 .Net 事件“:
bool condition1 = false;
bool condition2 = false;
bool condition3 = false;
event eventhandler VariableHasChanged;
aFunction1() { condition1 = true; VariableHasChanged(); }
aFunction2() { condition2 = true; VariableHasChanged(); }
aFunction3() { condition3 = true; VariableHasChanged(); }
VariableHasChanged += whenJobHasBeenCompleted;
whenJobHasBeenCompleted()
{
if( !( condition1 && condition2 && condition3 ) )
return;
// VariableHasChanged -= whenJobHasBeenCompleted
console.writeline("all three were done!");
}
这种类似状态机的方法可能是最容易理解的。在使用其他更复杂的工具之前,请先使用它进行训练,直到您对这种方法的优缺点有一个很好的了解。
现在,正如我所说,还有许多其他方法。
对于事件,您经常会遇到多线程和正确清理的问题。因此,您可以使用任何事件/通知框架,例如来自 Prism/CAG 的 WeakEvents 或 CompositeEvents,这些问题可能会消失。
您可以创建一组(智能)属性并绑定到它们而不是使用事件。如果使用任何 XAMLish UI,您可以轻松编写一个触发器/多重绑定,它将观察三个源并仅在设置所有三个源时才做出反应。
您可以采用工作线程和条件变量(或者您可以按照 Royi 的建议使用 TaskCompletionSource,它对您隐藏了大部分内容)。
您可以获取Rx Framework
和使用 hot-observable 而不是变量,并加入/过滤它们以创建过滤的事件流,该事件流仅在所有三个变量都设置为特定值时才 ping。
或者,您可以将 RX 与普通变量/事件一起使用,并将您的事件重新连接到 IObservable,如果您不喜欢它们,则无需任何“主题”和“OnNext”。
或者...