我有一个c#程序,其中function1
需要等待变量变为真,而不会阻塞程序。从外部脚本异步调用的function2
将变量设置为true。有没有办法可以在function1
中途等待,而不会阻止function2
被调用?在function 1
将变量设置为true后,我需要继续执行function2
的其余部分。
bool doneProcessing;
public void function1(string someParameter)
{
doneProcessing = false;
InvokeScript(somevalue);
//Wait till variable doneProcessing becomes true;
//Continue from here after doneProcessing is true
}
public void function2(string someParameter)
{
doneProcessing = true;
return;
}
答案 0 :(得分:3)
TaskCompletionSource是你的朋友
bool doneProcessing;
TaskCompletionSource < bool > tcs = new TaskCompletionSource < bool > ();
public void function1(string someParameter)
{
doneProcessing = false;
Task < bool > b = InvokeScript("IDontCare");
Console.WriteLine ("What's up?...");
b.ContinueWith(_ => Console.WriteLine("finished!")); //magic is here
Console.WriteLine ("Im not blocking...");
}
public Task < bool > function2(string someParameter)
{
new Thread(()=> {Thread.Sleep(2000); tcs.SetResult(true); /*this simulate putting true in doneProcessing variable*/}).Start();
return tcs.Task;
}
public Task < bool > InvokeScript(string someParameter)
{
return function2(someParameter);
}
void Main()
{
function1("1");
Console.ReadLine();
}
// output :What's up?...
Im not blocking...
finished
答案 1 :(得分:2)
最简单的方法可能是
function2
,以便当它结束时调用该函数Function2Complete
,并从function1
订阅。如果这不是您所要求的,请澄清。
答案 2 :(得分:0)
正如有人在评论中所说,你不能没有阻止地等待 但是,您可以等待而无需等待。
这完全取决于“等待”一词究竟是什么意思。
通常,您只需要在满足一组条件时执行一段代码即可。但这并不意味着你必须阻止任何事情。
考虑一下:
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”..
...或