2011-05-18 125 views
53

我知道如何使異步方法,但說我有一個方法,做了很多工作,然後返回一個布爾值?如何使一個異步方法返回一個值?

如何返回回調的布爾值?

澄清

public bool Foo(){ 
    Thread.Sleep(100000); // Do work 
    return true; 
} 

我希望能夠讓這個異步的。

回答

39

有這樣做的幾種方法......最簡單的就是有異步方法也做了後續操作。另一種流行的方法是在一個回調來傳遞,即

void RunFooAsync(..., Action<bool> callback) { 
    // do some stuff 
    bool result = ... 

    if(callback != null) callback(result); 
} 

另一種方法是提高一個事件(其結果在事件ARGS數據)時,異步操作完成。

此外,如果您使用的是第三方物流,可以使用ContinueWith

Task<bool> outerTask = ...; 
outerTask.ContinueWith(task => 
{ 
    bool result = task.Result; 
    // do something with that 
}); 
+0

回調方法的簡單例子 – DRapp 2016-10-15 14:09:17

1

使用BackgroundWorker。它可以讓你完成回調,並讓你跟蹤進度。您可以將事件參數的結果值設置爲結果值。

public void UseBackgroundWorker() 
    { 
     var worker = new BackgroundWorker(); 
     worker.DoWork += DoWork; 
     worker.RunWorkerCompleted += WorkDone; 
     worker.RunWorkerAsync("input"); 
    } 

    public void DoWork(object sender, DoWorkEventArgs e) 
    { 
     e.Result = e.Argument.Equals("input"); 
     Thread.Sleep(1000); 
    } 

    public void WorkDone(object sender, RunWorkerCompletedEventArgs e) 
    { 
     var result = (bool) e.Result; 
    } 
+0

後臺工作這裏是反生產力。你不知道AutoResetEvent/ManualResetEvent嗎? – 2011-05-18 13:25:13

+1

@ the_drow我不同意這一點;一個BackgroundWorker和RunWorkerCompleted事件在這裏是一個非常好的方法 – 2011-05-18 13:27:40

+0

@the_drow - 不,我不知道。我會看看我可以瞭解的。但如果你能解釋爲什麼你認爲這是反效果的,我想了解。 – NerdFury 2011-05-18 13:37:48

-1

你應該用你的異步方法的EndXXX返回值。 EndXXX應該等到使用IAsyncResult的WaitHandle有結果並返回值。

90

C# 5.0,你可以指定方法

public async Task<bool> doAsyncOperation() 
{ 
    // do work 
    return true; 
} 

bool result = await doAsyncOperation(); 
+19

對於任何關心的人來說,要使用'bool result = await doAsyncOperation();' – 2013-09-16 18:19:43

+1

每當你要使用「await」關鍵字時,它需要在方法,至少已標記爲「異步」。我原本雖然只有工人的方法必須這樣標記。例如,即使你的調用方法不會返回任何你必須命名爲「異步無效MyCallerMethod」 – 2014-10-27 16:52:53

+0

是的,但麻煩的警告,該方法將同步運行 – KingOfHypocrites 2015-06-18 17:25:51

3

也許這樣做是爲了創建一個委託,然後BeginInvoke,然後在未來的某個時間等待的最簡單方法,以及EndInvoke

public bool Foo(){ 
    Thread.Sleep(100000); // Do work 
    return true; 
} 

public SomeMethod() 
{ 
    var fooCaller = new Func<bool>(Foo); 
    // Call the method asynchronously 
    var asyncResult = fooCaller.BeginInvoke(null, null); 

    // Potentially do other work while the asynchronous method is executing. 

    // Finally, wait for result 
    asyncResult.AsyncWaitHandle.WaitOne(); 
    bool fooResult = fooCaller.EndInvoke(asyncResult); 

    Console.WriteLine("Foo returned {0}", fooResult); 
} 
+0

AsyncWaitHandle是一個WaitHandle。它沒有WaitOne()方法。你必須把它放在任何等待完成的地方。 – 2011-05-18 20:54:06

+0

@the_drow:你可能想看看這個例子:http://msdn.microsoft.com/en-us/library/system.iasyncresult.asyncwaithandle.aspx。另請參閱'WaitHandle.WaitOne'方法的文檔:http://msdn.microsoft.com/en-us/library/58195swd.aspx – 2011-05-18 21:08:39

+1

或者您可以將該代碼粘貼到C#程序中並對其進行測試。它似乎爲我工作。 – 2011-05-18 21:19:38

1

或許你可以嘗試的BeginInvoke委託指向你的方法,像這樣:

 


    delegate string SynchOperation(string value); 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      BeginTheSynchronousOperation(CallbackOperation, "my value"); 
      Console.ReadLine(); 
     } 

     static void BeginTheSynchronousOperation(AsyncCallback callback, string value) 
     { 
      SynchOperation op = new SynchOperation(SynchronousOperation); 
      op.BeginInvoke(value, callback, op); 
     } 

     static string SynchronousOperation(string value) 
     { 
      Thread.Sleep(10000); 
      return value; 
     } 

     static void CallbackOperation(IAsyncResult result) 
     { 
      // get your delegate 
      var ar = result.AsyncState as SynchOperation; 
      // end invoke and get value 
      var returned = ar.EndInvoke(result); 

      Console.WriteLine(returned); 
     } 
    } 
 

然後使用您發送的AsyncCallback的繼續該方法的價值..