1

J'ai une méthode qui enregistre une tâche d'arrière-plan qui ressemble à ceci:Annulation d'une tâche complète lorsqu'une méthode appelée ne retourne pas

//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; 
} 

Mon problème est que parfois la méthode builder.Register() ne retourne pas n'importe quoi. C'est probablement un bug de Windows; la méthode Register() ne se termine jamais en interne. En effet, après 10 secondes, la méthode token.ThrowIfCancellationRequested() est appelée, mais elle n'est pas envoyée à l'instruction try-catch où elle est appelée. Initialement, j'appelais builder.Register() directement sans Task.Run() mais cela ne fonctionnait pas, et cela non plus.

Cependant, si je remplace btr = Task.Run(() =>... avec un Task.Delay(ms) à la place, où ms > 10000, mon effet prévu se produit.

Est-ce que je fais quelque chose de mal? Ou y a-t-il une meilleure façon de faire cela? Fondamentalement, j'ai juste besoin de code qui fera que la méthode registerTask() retourne null lorsque builder.Register() ne se termine pas après quelques secondes.

+0

L'utilisation de '.Result' est problématique car cela bloquerait le thread; pouvez-vous utiliser les fonctions async et 'await' à la place? – Jacob

+0

@Jacob Peut-être que c'est ce qui se passe? Je fais cela à partir d'un projet Windows Runtime donc je ne peux pas faire ma tâche async, mon erreur de compilation dit quelque chose comme je devrais changer le type "Task" en IAsyncAction ou quelque chose mais je ne l'ai pas encore fait – Tyress

Répondre

0

Remplacement du code avec quelque chose comme ça a fonctionné pour moi:

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); 

Au lieu de traiter l'erreur, obtenir une demande d'annulation déclenchera une des tâches à la fin, et quand il se termine je reviens l'enregistrement des tâches variable, qu'elle soit nulle ou non.