为了避免 GUI 冻结,我想运行异步连接数据库的方法。因此我写了这个:
DelegatLoginu dl = ConnectDB;
IAsyncResult ar = dl.BeginInvoke(null, null);
var result = (bool)dl.EndInvoke(ar);
但它仍然很冷,我不明白为什么。我认为BeginInvoke
确保调用的代码在另一个线程中运行。谢谢!
为了避免 GUI 冻结,我想运行异步连接数据库的方法。因此我写了这个:
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() ) );
}
请参阅EndInvoke
此处的描述,具体为:
EndInvoke() 函数用于检索异步调用的结果。它可以在 BeginInvoke() 之后的任何时间调用。如果异步调用尚未完成,EndInvoke() 将阻塞直到完成。
调用时您会立即阻塞您的 UI 线程dl.EndInvoke(ar)
。这种方式违背了进行异步调用的全部目的。
在 .NET 中使用异步模型有 4 种不同的模式,因为这个问题很好地涵盖了。
您正在使用“我会打电话给您”的方法。但是,如果您想等到工作项完成,最好的技术是使用Mutex
(the 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()
{
}
我怀疑您不想阻止,在这种情况下,“一劳永逸”会引起最少的头痛。
在 BeginInvoke 中指定调用完成时要调用的方法(如 dl.BeginInvoke(null, OnConnectCompleted))。然后线程不会被阻塞。
为什么不直接使用BackgroundWorker呢?
调用 EndInvoke 将阻塞您当前的线程。您应该将委托传递给 BeginInvoke 而不是调用 EndInvoke