等待变量而不阻塞

时间:2013-07-17 07:03:39

标签: c# multithreading

我有一个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;

  }

3 个答案:

答案 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”..

  • ...或