为什么我的BeginInvoke方法不是异步的?

时间:2010-05-05 09:24:07

标签: c# multithreading begininvoke

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

DelegatLoginu dl = ConnectDB;

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

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

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

7 个答案:

答案 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种不同的模式。

您正在使用“我会称之为”方法。但是,如果您想等到工作项完成,最好的方法是使用MutexWaitHandle):

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