Вот фрагмент кода от Microsoft. У меня есть сомнение в асинхронном вызове метода.
поскольку мы вызываем end.Invoke после Begin-invoke, похоже, что мы делаем синхронный вызов. потому что мы ждем возвращенного значения асинхронного вызова.
что произойдет, если асинхронный метод не завершится, пока мы вызываем end.invoke. можем ли мы просто перейти к следующему утверждению или нам нужно подождать.
если это происходит в многопоточной среде, как они обрабатывают сигнал обратного вызова для исправления потока.
public void DemoEndInvoke()
{
MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
string s ;
int iExecThread;
// Initiate the asynchronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
// Do some useful work here. This would be work you want to have
// run at the same time as the asynchronous call.
// Retrieve the results of the asynchronous 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() ) );
}
что произойдет, если асинхронный метод не завершится, пока мы вызываем end.invoke. можем ли мы просто перейти к следующему утверждению или нам нужно подождать.
Да, EndInvoke
- это блокирующий вызов. Вы можете сделать все это намного проще, если вы используете метод TaskFactory.FromAsync. Это преобразует ваш API, чтобы вернуть задачу, которую вы можете await
.
Ваш код должен выглядеть примерно так (я его не компилировал):
public async void DemoEndInvoke()
{
MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
string s ;
int iExecThread;
await Task.Factory.FromAsync(MethodDelegate.BeginInvoke, MethodDelegate.EndInvoke, iExecThread);
MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\", and the number {1}", s, iExecThread.ToString() ) );
}
Используя await
компилятор будет генерировать конечный автомат, который сохраняет текущий SynchronizationContext
а затем восстанавливает его после завершения задачи и выполняет оставшуюся часть метода в том же SynchronizationContext
. Если вы await
в потоке пользовательского интерфейса, код после await
также будет выполняться в потоке пользовательского интерфейса. Однако для консольных приложений и модульных тестов это не так.
Если все, что вы пытаетесь сделать, это запустить длинный метод в фоновом потоке, вы можете просто использовать Task.Run в.net 4.5 или TaskFactory.StartNew в.net 4.0. Разницу между ними см. В этой статье.
public async void DemoEndInvoke()
{
await Task.Run(() => this.LongRunningMethod());
MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\", and the number {1}", s, iExecThread.ToString() ) );
}
Вам придется подождать; от синхронных асинхронных вызовов:
EndInvoke может блокировать вызывающий поток, поскольку он не возвращается до завершения асинхронного вызова
Механизм, который используется для выполнения блокировки, скорее всего будет выглядеть следующим образом:
IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
// wait for async invocation to complete
ar.AsyncWaitHandle.WaitOne()
Но вы должны позвонить EndInvoke (см. Этот вопрос для более подробного обсуждения).
Если вы не хотите ждать, вам необходимо использовать асинхронный обратный вызов для выполнения EndInvoke
:
dlgt.BeginInvoke(3000, out iExecThread, ar => dlgt.EndInvoke(out iExecThread, ar), null);
Когда вы это сделаете, вы не узнаете результаты своего асинхронного вызова; вы не можете получить возвращаемое значение, и вы не будете знать, какие сделаны изменения каких - либо out
параметров (контр-интуитивно, BeginInvoke
не меняет какой - либо из его out
параметров на всех).
С учетом сказанного,.NET получил отличные асинхронные API программирования, начиная с.NET 4; более новые модели лучше структурированы, более мощные и удобны в работе (особенно в 4.5). Если у вас есть этот параметр, вы должны посмотреть .NET TPL и .NET 4.5 TAP.
MethodDelegate.BeginInvoke
выполнить в фоновом потоке, что, в свою очередь, сообщаетthis.LongRunningMethod
о запуске в фоновом потоке; там много дополнительной работы.