Почему моя задача задержки не вызывает Task.WaitAny () - PullRequest
0 голосов
/ 01 ноября 2018

Итак, у меня есть следующее:

if (await Task.WhenAny(myLongRunningTask, Task.Delay(9000)) != myLongRunnnigTask && !myLongRunningTask.IsFaulted)
{
    Console.WriteLine("TimedOut");
}
else
{
    Console.WriteLine("Completed");
}

Кажется, работает нормально, когда я завершу свою задачу; но если я никогда не завершу долгосрочную задачу, то это просто зависает, а не по истечении 9 секунд. Даже поставить ошибочный тест, чтобы быть уверенным.

(ПРИМЕЧАНИЕ. Реальный код делает больше, чем просто запись в командной строке; но он никогда даже не попадает в сферу; хотя я тоже пробовал писать только в командной строке ... без изменений.)

Тем не менее, делать то, что мне кажется, в LinqPad точно так же:

async void Main()
{
    var Other = Task.Factory.StartNew(() => { Thread.Sleep(15000); });
    if(await Task.WhenAny(Other, Task.Delay(4000)) != Other && !Other.IsFaulted) "TimedOut".Dump();
    else "Completed".Dump();

    Other = Task.Factory.StartNew(() => { Thread.Sleep(1000); });
    if(await Task.WhenAny(Other, Task.Delay(4000)) != Other && !Other.IsFaulted) "TimedOut".Dump();
    else "Completed".Dump();
}

К счастью, пишет TimedOut, а затем Completed.

Первый раздел кода глубоко в довольно большом модуле. Но я не понимаю, что может побочно повлиять на это странное поведение ... Чего мне не хватает?

ПРИМЕЧАНИЕ по принятому ответу:

Вопрос здесь заключался в том, что может быть побочным эффектом. Ответ @Douglas 'указывает на побочный эффект, который повлиял на мой код. Это не обязательно решает проблему; просто говорит вам, где ваша проблема. Однако он услужливо добавил комментарий со ссылкой на статью, которая действительно поможет вам исправить это.

Ответы [ 2 ]

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

Но я не понимаю, что может побочно повлиять на это странное поведение ...

Вашему longRunningTask, вероятно, присвоено возвращаемое значение метода, подобного:

private static Task NewMethod()
{
    Thread.Sleep(11000);
    return Task.CompletedTask;
}

затем позже:

var myLongRunningTask = NewMethod();

Таким образом, к тому времени, когда вы достигнете линии var readyTask = await, 11-секундный сон («длительное задание») уже уже произошел (поскольку NewMethod не является асинхронным), и, таким образом, Task.WhenAny возвращается мгновенно (так как longRunningTask завершено).

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

Это может произойти, если вы блокируете этот асинхронный метод из контекста синхронизации, который выполняет продолжения в исходном потоке, таком как интерфейс WPF или WinForms. Попробуйте добавить ConfigureAwait(false) и проверьте, избегает ли это зависания:

var readyTask = await Task.WhenAny(myLongRunningTask, Task.Delay(9000)).ConfigureAwait(false);
if (readyTask != myLongRunnnigTask && !myLongRunningTask.IsFaulted)
{
    Console.WriteLine("TimedOut");
}
else
{
    Console.WriteLine("Completed");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...