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

Чтобы постараться не замораживаться GUI, я хотел выполнить метод, соединяющийся с DB асинхронно. Поэтому я записал это:

DelegatLoginu dl = ConnectDB;

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

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

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

8
задан Drew Noakes 20 April 2017 в 22:38
поделиться

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() ) );
}
12
ответ дан 5 December 2019 в 08:22
поделиться

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

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

5
ответ дан 5 December 2019 в 08:22
поделиться

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

2
ответ дан 5 December 2019 в 08:22
поделиться

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

0
ответ дан 5 December 2019 в 08:22
поделиться

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

0
ответ дан 5 December 2019 в 08:22
поделиться

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

0
ответ дан 5 December 2019 в 08:22
поделиться

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

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

1
ответ дан 5 December 2019 в 08:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: