为了避免冻结GUI,我想运行异步连接到DB的方法。因此我写了这个:
DelegatLoginu dl = ConnectDB;
IAsyncResult ar = dl.BeginInvoke(null, null);
var result = (bool)dl.EndInvoke(ar);
但它仍然冻结,我不明白为什么。我以为BeginInvoke
确保调用的代码在另一个线程中运行。谢谢!
答案 0 :(得分: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() ) );
}
答案 1 :(得分:5)
请参阅EndInvoke
here的说明,具体为:
EndInvoke()函数用于 检索结果 异步调用。它可以被称为 在BeginInvoke()之后的任何时间。如果 异步调用尚未完成 但是,EndInvoke()会阻塞它 完成。
答案 2 :(得分:2)
调用dl.EndInvoke(ar)
时,您会立即阻止您的UI线程。这种方式违背了异步呼叫的全部目的。
答案 3 :(得分:1)
在.NET as this question中使用异步模型有4种不同的模式。
您正在使用“我会称之为”方法。但是,如果您想等到工作项完成,最好的方法是使用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()
{
}
我怀疑你不想阻止,在这种情况下“火与忘记”导致最少的头痛。
答案 4 :(得分:0)
指定在BeginInvoke中完成调用时要调用的方法(如dl.BeginInvoke(null,OnConnectCompleted))。然后线程不会被阻止。
答案 5 :(得分:0)
为什么不使用BackgroundWorker呢?
答案 6 :(得分:0)
调用EndInvoke将阻止当前线程。您应该将委托传递给BeginInvoke而不是调用EndInvoke