Почему мой метод BeginInvoke не асинхронный? - PullRequest
8 голосов
/ 05 мая 2010

Чтобы избежать зависания графического интерфейса, я хотел запустить метод подключения к БД асинхронно. Поэтому я написал это:

DelegatLoginu dl = ConnectDB;

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

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

Но все еще холодно, и я не понимаю, почему. Я думал, BeginInvoke гарантирует, что вызванный код выполняется в другом потоке. Спасибо!

Ответы [ 7 ]

12 голосов
/ 05 мая 2010

Вызов 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() ) );
}
5 голосов
/ 05 мая 2010

См. Описание EndInvoke здесь , в частности:

Функция EndInvoke () используется для получить результаты асинхронный вызов. Это можно назвать в любое время после BeginInvoke (). Если асинхронный вызов не завершен пока EndInvoke () блокируется до завершается.

2 голосов
/ 05 мая 2010

Вы немедленно блокируете свой поток пользовательского интерфейса при вызове dl.EndInvoke(ar). Этот вид поражает всю цель асинхронного вызова.

1 голос
/ 12 мая 2010

Существует 4 различных шаблона использования асинхронной модели в .NET , так как этот вопрос очень хорошо подходит.

Вы используете "Я позвоню тебе" подход . Однако, если вы хотите подождать, пока рабочий элемент не будет завершен, лучше всего использовать 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()
{
}

Я подозреваю, что вы не хотите блокировать, и в этом случае "выстрели и забудь" вызывает наименьшую головную боль.

0 голосов
/ 05 мая 2010

Вызов EndInvoke заблокирует ваш текущий поток. Вы должны передать делегат в BeginInvoke вместо вызова EndInvoke

0 голосов
/ 05 мая 2010

Почему бы просто не использовать BackgroundWorker вместо этого?

0 голосов
/ 05 мая 2010

Укажите метод, который будет вызываться при завершении вызова в BeginInvoke (например, dl.BeginInvoke (null, OnConnectCompleted)). Тогда поток не будет заблокирован.

...