Могу ли я гарантировать, что запущенные продолжения задач были выполнены? - PullRequest
0 голосов
/ 03 ноября 2018

Вот значительно сокращенный тестовый пример из кода, над которым я работаю:

var i = 0;

var taskCompletionSource = new TaskCompletionSource<object>();
var task = taskCompletionSource.Task;

Task.Run(async () => 
{
    await task;
    i = 1;
});

// Synchronously complete `task`
taskCompletionSource.SetResult(null);

// ???

Console.WriteLine(i);

Предполагая, что этот код выполняется в контексте метода async, что должно заменить // ???, чтобы этот код печатал 1 вместо 0?

Полагаю, я понимаю, почему при написании программа всегда печатает 0 - код выполняется синхронно, и планировщик ничего не передал. Но я удивлен, узнав, что

await Task.Yield();

не достаточно. Несколько иронично (но вполне понятно, учитывая, что оно не включает асинхронного выполнения), а также

await task;

С другой стороны,

await Task.Delay(1);

кажется достаточно, но мне не ясно, является ли это гарантией или случайностью выбора времени.

Чтобы задать вопрос еще раз: есть ли какой-нибудь (разумный) код, который я могу написать, который будет гарантировать, что все продолжения для task были выполнены перед продолжением?

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Могу ли я гарантировать, что запущенные продолжения задачи были выполнены?

По await их.

var i = 0;

var taskCompletionSource = new TaskCompletionSource<object>();
var task = taskCompletionSource.Task;

var continuation = Task.Run(async () => 
{
    await task;
    i = 1;
});

// Synchronously complete `task`
taskCompletionSource.SetResult(null);

// wait for the continuation
await continuation;

// ouputs 1
Console.WriteLine(i);

Это работает, если вы используете асинхронный метод. Если нет, сделайте это асинхронным. Вы также можете технически заблокировать (.Wait() вместо await), но это вызывает взаимоблокировки, поэтому будьте осторожны.

0 голосов
/ 03 ноября 2018

Предполагается, что этот код выполняется в контексте асинхронного метода

var i = 0;

await Task.Run(async () => 
{
    await task;
    i = 1;
});

Console.WriteLine(i);

или

var i = 0;

await task;
i = 1;

Console.WriteLine(i);
...