Чтобы постараться не замораживаться GUI, я хотел выполнить метод, соединяющийся с DB асинхронно. Поэтому я записал это:
DelegatLoginu dl = ConnectDB;
IAsyncResult ar = dl.BeginInvoke(null, null);
var result = (bool)dl.EndInvoke(ar);
Но все еще замораживается, и я не понимаю почему. Я думал BeginInvoke
гарантирует вызванные выполнения кода в другом потоке.Спасибо!
Вызов 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)
. Этот вид побеждает всю цель асинхронного вызова.
Укажите в BeginInvoke метод, который будет вызван после завершения вызова (например, dl.BeginInvoke(null, OnConnectCompleted)). Тогда поток не будет блокироваться.
Почему бы вместо этого просто не использовать BackgroundWorker?
Вызов EndInvoke заблокирует текущий поток. Вы должны передать делегата в BeginInvoke вместо вызова EndInvoke
Существует 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()
{
}
Я подозреваю, что вы не хотите блокировать , в этом случае «выстрелил и забыл» вызывает наименьшую головную боль.