Почему мой метод BeginInvoke не асинхронный?

чтобы избежать замораживания GUI, я хотел запустить метод подключения к БД асинхронно. Поэтому я написал следующее:--3-->

DelegatLoginu dl = ConnectDB;

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

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

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

7 ответов


вызов 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 () блокирует, пока он завершает.


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


существует 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()
{
}

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


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


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


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