爲了避免GUI凍結,我想運行連接到數據庫的方法異步。所以我寫了這個:爲什麼我的BeginInvoke方法不是異步?
DelegatLoginu dl = ConnectDB;
IAsyncResult ar = dl.BeginInvoke(null, null);
var result = (bool)dl.EndInvoke(ar);
但它仍然凍結,我不明白爲什麼。我認爲BeginInvoke
可以確保調用的代碼在另一個線程中運行。謝謝!
爲了避免GUI凍結,我想運行連接到數據庫的方法異步。所以我寫了這個:爲什麼我的BeginInvoke方法不是異步?
DelegatLoginu dl = ConnectDB;
IAsyncResult ar = dl.BeginInvoke(null, null);
var result = (bool)dl.EndInvoke(ar);
但它仍然凍結,我不明白爲什麼。我認爲BeginInvoke
可以確保調用的代碼在另一個線程中運行。謝謝!
調用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()));
}
當您撥打dl.EndInvoke(ar)
時,您會立即阻止您的UI線程。這種做法違背了異步調用的全部目的。
見EndInvoke
here的描述,具體是:
的EndInvoke會()函數用於 檢索異步調用的結果 。它可以在BeginInvoke()之後的任何時候被調用 。如果 異步調用尚未完成 ,則EndInvoke()會阻止,直到它完成 。
指定在BeginInvoke中調用完成時要調用的方法(如dl.BeginInvoke(null,OnConnectCompleted))。然後線程不會被阻塞。
爲什麼不直接使用BackgroundWorker呢?
調用EndInvoke會阻止當前線程。您應該將代理傳遞給BeginInvoke,而不是調用EndInvoke。
有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()
{
}
我懷疑你不想阻止,在這種情況下「火忘記「導致最少的頭痛。
我需要使用AsyncCallBack類還是可以傳遞簡單委託? – Petr 2010-05-05 09:36:17
它必須是AsyncCallBack委託,即你的函數必須看起來像上面的MyAsyncCallback()例子 - 返回void,並將IAsyncResult作爲參數。 – RickL 2010-05-05 09:40:28
我已經在本地測試了這段代碼,它不起作用(它會編譯,但它不會在屏幕上顯示任何內容):http://ideone.com/V8b2NY – InfZero 2014-06-14 23:13:55