1

У меня есть метод, который регистрирует фоновую задачу, которая выглядит следующим образом:Отменять всю задачу, когда вызываемый метод не возвращает

//snippet from task builder method 
     try 
     { 
      cancellationTokenSource.CancelAfter(10000); 
      btr = Task.Run(() => registerTask(builder, btr,cancellationTokenSource.Token), cancellationTokenSource.Token).Result; 
     } 
     catch (OperationCanceledException) // something went wrong 
     { 
      return null; 
     } 



private BackgroundTaskRegistration registerTask(BackgroundTaskBuilder builder, BackgroundTaskRegistration btr, CancellationToken token) 
{ 
    CancellationTokenSource newToken = new CancellationTokenSource(); 
    Task cancelledCheck = Task.Run(() => 
    { 
     while (true) 
     { 
      if (token.IsCancellationRequested) 
      { 
       newToken.Cancel(); 
       token.ThrowIfCancellationRequested(); 
      } 
     } 
    }, newToken.Token); 
    btr = Task.Run(()=> builder.Register(),token).Result; 
    return btr; 
} 

Моя проблема заключается в том, что иногда метод builder.Register() не возвращает что-нибудь. Вероятно, это ошибка Windows; метод Register() никогда не заканчивается внутренне. Действительно, через 10 секунд вызывается метод token.ThrowIfCancellationRequested(), но он не бросает в оператор try-catch, где он вызывается. Первоначально я вызывал builder.Register() непосредственно без Task.Run(), но это не сработало, и это тоже не так.

Однако, если я заменил btr = Task.Run(() =>... на Task.Delay(ms), где ms > 10000, мой предполагаемый эффект произойдет.

Я что-то не так? Или есть лучший способ сделать это? В основном мне нужен только код, который сделает метод registerTask() возвратом null в builder.Register() не завершится через несколько секунд.

+0

Использование '.Result' проблематично, так как это заблокирует поток; вы можете использовать асинхронные функции и «ждать»? – Jacob

+0

@Jacob Возможно, это то, что происходит? Я делаю это из проекта Windows Runtime, поэтому я не могу выполнить свою задачу async, моя ошибка компиляции говорит о том, что я должен изменить тип «Задача» на IAsyncAction или что-то еще, но я еще этого не сделал – Tyress

ответ

0

Замена кода с чем-то вроде этого работал для меня:

btr = null; 
    cancellationTokenSource.CancelAfter(10000); 
    Task registerTask = Task.Factory.StartNew(() => 
    { 
     btr = builder.Register(); 
    }); 
    Task cancellationTask = Task.Factory.StartNew(() => 
    { 
    while (true) 
    { 
     if (cancellationTokenSource.Token.IsCancellationRequested) break; 
    } 
    }, cancellationTokenSource.Token); 
    Task[] tasks = new Task[2] { cancellationTask, registerTask }; 
    Task.WaitAny(tasks); 

Вместо обработки ошибки, получая запрос на отмену вызовет одну из задач до конца, и когда он заканчивается, я вернуть регистрацию задачи переменная, является ли она нулевой или нет.

Смежные вопросы