Разбираюсь в async/await. Вот такой код в WinForms (чтобы был UI-контекст):
private async void Parent(){
Write("Parent() start.");
var context = SynchronizationContext.Current;
Task task = Task.Run(()=>ChildAsync(context));
while (!task.IsCompleted)
{
Write("loop");
await Task.Delay(1000);
}
Write("Parent() done.");
}
private async Task ChildAsync(SynchronizationContext context)
{
await Task.Delay(3000);
}
public void Write(string message){
richTextBox1.AppendText($"\n{message}");
}
Почему в коде метода ChildAsync вызов функции Write() мешает дальнейшему выполнение кода, но при этом не мешает задаче завершиться (ведь сообщение Parent() done. появляется):
При этом если Write() вызвать после await, то это не мешает выполнению задачи:
И еще меня сильно смущает, что программа выводит сообщение "loop" хотя бы один раз - если Write() вызывает эксепшен и завершает задачу, то почему программа все же один раз входит в цикл?
Изменение задержки не помогает:
private async void Parent(){
Write("Parent() start.");
var context = SynchronizationContext.Current;
Task task = Task.Run(() => ChildAsync(context));
while (!task.IsCompleted)
{
await Task.Delay(5000);
Write("loop");
}
Write("Parent() done.");
}
private async Task ChildAsync(SynchronizationContext context)
{
Write(".......ChildAsync() done.");
context.Post((x) => Write(".......ChildAsync() done"), null);
await Task.Delay(3000);
}
Заключил код по созданию task'a в try-catch, но он не ловит ошибку. Почему?
private async void Parent(){
Write("Parent() start.");
var context = SynchronizationContext.Current;
Task task = null;
try
{
task = Task.Run(() => ChildAsync(context));
}
catch (Exception e)
{
MessageBox.Show(task.Exception.InnerException.Message);
}
while (!task.IsCompleted)
{
await Task.Delay(1000);
Write("loop");
}
Write("Parent() done.");
}
Вы, наверное, думаете, что эксепшон в таске должен выкидывать вас из цикла. Нет, тот эксепшон остается в таске (если вы не делаете await mytask), то есть раз в основном потоке вы успели зайти в цикл, то код в цикле выполнится, хоть час ждите. Вот если вы await Task.Delay(5000); поставите перед циклом while, а не внутри цикла, то тогда да, в цикл не попадете, за 5 сек таск успеет упасть
Продвижение своими сайтами как стратегия роста и независимости