在不阻塞的情况下等待变量
本文关键字:情况下 等待 变量 | 更新日期: 2023-09-27 18:23:35
我有一个c#程序,其中function1
需要在不阻塞程序的情况下等待变量变为true。从外部脚本异步调用的function2
将变量设置为true。有没有一种方法可以在不阻止调用function2
的情况下在function1
中中途等待?在function2
将变量设置为true之后,我需要继续执行function 1
的其余部分。
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;
}
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
最简单的方法可能是
- 将委托传递到
function2
中,以便在其结束时调用该函数 - 或者创建自定义事件(例如)
Function2Complete
并且从function1
订阅它
如果这不是你想要的,请澄清。
正如有人在评论中所说,你不能不阻止就等待
但是,您可以等待而不必等待。
这完全取决于你所说的"等待"这个词到底是什么意思。
通常,您只希望在满足一组条件时执行一段代码。但这并不意味着你必须阻止任何事情。
考虑一下:
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!");
}
这种类似状态机的方法可能是最容易理解的。在使用其他更复杂的工具之前,请使用它进行培训,直到您对这种方法的优缺点有了很好的了解。
现在,正如我所说,有许多其他方式。
对于事件,您经常会遇到多线程和正确清理的问题。因此,您可以使用任何Eventing/Notification框架,例如来自Prism/CAG的WeakEvents或CompositeEvents,这些问题可能会消失。
您可以创建一组(智能)属性并绑定到它们,而不是使用事件。如果使用任何XAMLish UI,您可以很容易地编写一个触发器/多绑定,它将观察三个源,并仅在三个源都设置好时做出反应。
你可以使用一个工作线程和条件变量(或者你可以像Royi建议的那样使用TaskCompletionSource,它对你隐藏了大部分)。
您可以获取
Rx Framework
,并使用热可观察而不是变量,并将它们连接/过滤以创建一个过滤的事件流,该流仅在所有三个变量都设置为特定值时发出ping信号。或者,如果你不喜欢,你可以将RX与普通变量/事件一起使用,并将你的事件重新连接到IObservable中,而不需要任何"主题"answers"OnNext"。。
或者。。。