0

我有 ac# 程序,function1需要等待变量变为真而不阻塞程序。function2从外部脚本异步调用将变量设置为 true。有没有一种方法可以让我在中途等待function1而不会 function2被呼叫?在将变量设置为 truefunction 1之后,我需要继续执行其余的操作。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;

  }
4

3 回答 3

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
于 2013-07-17T07:19:03.307 回答
2

最简单的方法可能是

  • 将委托传递给function2它,以便在它结束时调用该函数
  • 或创建一个自定义事件(比如)Function2Complete,然后function1订阅它。

如果这不是您要的,请澄清。

于 2013-07-17T07:06:55.233 回答
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”。

  • 或者...

于 2013-07-17T08:10:01.460 回答