8

为了避免 GUI 冻结,我想运行异步连接数据库的方法。因此我写了这个:

DelegatLoginu dl = ConnectDB;

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

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

但它仍然很冷,我不明白为什么。我认为BeginInvoke确保调用的代码在另一个线程中运行。谢谢!

4

7 回答 7

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() ) );
}
于 2010-05-05T09:26:52.787 回答
5

请参阅EndInvoke 此处的描述,具体为:

EndInvoke() 函数用于检索异步调用的结果。它可以在 BeginInvoke() 之后的任何时间调用。如果异步调用尚未完成,EndInvoke() 将阻塞直到完成。

于 2010-05-05T09:27:38.993 回答
2

调用时您会立即阻塞您的 UI 线程dl.EndInvoke(ar)。这种方式违背了进行异步调用的全部目的。

于 2010-05-05T09:26:27.247 回答
1

在 .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()
{
}

我怀疑您不想阻止,在这种情况下,“一劳永逸”会引起最少的头痛。

于 2010-05-12T09:26:16.127 回答
0

在 BeginInvoke 中指定调用完成时要调用的方法(如 dl.BeginInvoke(null, OnConnectCompleted))。然后线程不会被阻塞。

于 2010-05-05T09:28:38.397 回答
0

为什么不直接使用BackgroundWorker呢?

于 2010-05-05T09:48:02.083 回答
0

调用 EndInvoke 将阻塞您当前的线程。您应该将委托传递给 BeginInvoke 而不是调用 EndInvoke

于 2010-05-05T10:57:12.147 回答