Почему мой метод 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)). Тогда поток не будет заблокирован.
вызов EndInvoke заблокирует текущий поток. Вы должны передать делегат в BeginInvoke вместо вызова EndInvoke