2010-05-05 79 views
8

爲了避免GUI凍結,我想運行連接到數據庫的方法異步。所以我寫了這個:爲什麼我的BeginInvoke方法不是異步?

DelegatLoginu dl = ConnectDB; 

IAsyncResult ar = dl.BeginInvoke(null, null); 

var result = (bool)dl.EndInvoke(ar); 

但它仍然凍結,我不明白爲什麼。我認爲BeginInvoke可以確保調用的代碼在另一個線程中運行。謝謝!

回答

12

調用EndInvoke()會阻塞,直到BeginInvoke()調用完成。

你需要這種模式,以便爲您的長時間運行的方法來調用回調當它完成:

public void DemoCallback() 
{ 
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ; 
    string s ; 
    int iExecThread; 

    // Create the callback delegate. 
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback); 

    // Initiate the Asynchronous call passing in the callback delegate 
    // and the delegate object used to initiate the call. 
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt); 
} 

public void MyAsyncCallback(IAsyncResult ar) 
{ 
    string s ; 
    int iExecThread ; 

    // Because you passed your original delegate in the asyncState parameter 
    // of the Begin call, you can get it back here to complete the call. 
    MethodDelegate dlgt = (MethodDelegate) ar.AsyncState; 

    // Complete the call. 
    s = dlgt.EndInvoke (out iExecThread, ar) ; 

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\", 
           and the number {1}", s, iExecThread.ToString())); 
} 
+0

我需要使用AsyncCallBack類還是可以傳遞簡單委託? – Petr 2010-05-05 09:36:17

+1

它必須是AsyncCallBack委託,即你的函數必須看起來像上面的MyAsyncCallback()例子 - 返回void,並將IAsyncResult作爲參數。 – RickL 2010-05-05 09:40:28

+0

我已經在本地測試了這段代碼,它不起作用(它會編譯,但它不會在屏幕上顯示任何內容):http://ideone.com/V8b2NY – InfZero 2014-06-14 23:13:55

2

當您撥打dl.EndInvoke(ar)時,您會立即阻止您的UI線程。這種做法違背了異步調用的全部目的。

+0

嗯,這是mz guess ..所以這有什麼好處?我認爲它在背景中完成了所有的連接,然後只返回:( – Petr 2010-05-05 09:32:03

+0

)'BeginXxx'在調用之後返回,此時連接的內容正在後臺處理。當結果準備就緒時,您將獲得(或者通過回調或者通過輪詢'BeginXxx'調用返回的'IAsyncResult'中的'WaitHandle')來實現的,此時您調用EndXxx來檢索結果(或者獲取調用中發生的異常)早期調用'EndXxx'強制等待,直到結果準備好。 – Lucero 2010-05-05 09:37:02

5

EndInvokehere的描述,具體是:

的EndInvoke會()函數用於 檢索異步調用的結果 。它可以在BeginInvoke()之後的任何時候被調用 。如果 異步調用尚未完成 ,則EndInvoke()會阻止,直到它完成 。

0

指定在BeginInvoke中調用完成時要調用的方法(如dl.BeginInvoke(null,OnConnectCompleted))。然後線程不會被阻塞。

0

調用EndInvoke會阻止當前線程。您應該將代理傳遞給BeginInvoke,而不是調用EndInvoke。

1

有4種不同的模式可以很好地使用.NET中的異步模型as this question

您正在使用「我給你打電話」方法。但是,如果你想等到工作項目完成後,最好的方法是使用一個Mutex(在WaitHandle):

void Run() 
{ 
    Action<string> doWork = DoWork; 
    IAsyncResult result = doWork.BeginInvoke("I will call you", null, null); 

    // You "call the method" - wait 10 seconds for the method to finish. 
    bool success = result.AsyncWaitHandle.WaitOne(10 * 1000); 
} 

void DoWork() 
{ 
} 

我懷疑你不想阻止,在這種情況下「火忘記「導致最少的頭痛。

相關問題