2014-09-10 3 views
0

Je travaille sur le remplacement de mon ancien code qui utilise des threads à un système basé sur les tâches .NET 4.5.Comment utiliser Await Task.Delay sans étiqueter toutes les méthodes Async?

J'ai remplacé les discussions avec des tâches, à côté, je travaille sur le remplacement de mon Thread.Sleep appelle avec Attendent Task.Delay. Les problèmes que j'ai avec ceci est que l'attente ne peut pas être appelée dans une section Synclock et également chaque méthode qui utilise maintenant Await Task.Delay doit à la place être appelée Async.

Je peux probablement contourner le problème SYNCLOCK que je n'ai que quelques blocs de ceux-ci et peut être remplacé par un meilleur code. Cependant, devoir étiqueter chaque méthode Async pose des problèmes. Cela signifie que je dois étiqueter la méthode qui appelle cette méthode Async et ainsi de suite dans la chaîne. Finalement, toutes mes méthodes vont être Async.

Est-ce la façon dont il devrait être fait lors de l'utilisation d'une approche basée sur les tâches ou que je fais mal?

Edit 1: Affichage exemple de code

Public Async Function Delay(Milliseconds As Integer, Optional Initial As Boolean = False, Optional Silent As Boolean = False, Optional Modifier As Double = 0.3, _ 
         Optional Task As Task = Nothing, Optional ExitOnTaskStop As Boolean = True) As Tasks.Task(Of Boolean) 
    Dim OutputBufferKey As String = Nothing 

    If Task IsNot Nothing Then 
     If Task.StopRequested Then Return True 
     OutputBufferKey = Task.OutputBufferKey 
    End If 

    If Initial Then 
     Milliseconds = Rand.Next(0, Milliseconds) 
    ElseIf Modifier > 0 Then 
     Dim MinValue As Integer = CInt(Milliseconds * (1 - Modifier)) 
     Dim MaxValue As Integer = CInt(Milliseconds * (1 + Modifier)) 
     If MinValue < MaxValue Then Milliseconds = Rand.Next(MinValue, MaxValue + 1) 
    End If 

    If DebugMode AndAlso Not Silent Then 
     Dim LengthString As String = Nothing 
     Select Case Milliseconds 
     Case Is < 60 * 1000 : LengthString = Math.Round(Milliseconds/1000, 1) & " seconds" 
     Case Is < 60 * 60 * 1000 : LengthString = Math.Round(Milliseconds/(60 * 1000), 1) & " minutes" 
     Case Else : LengthString = Math.Round(Milliseconds/(60 * 60 * 1000), 1) & " hours" 
     End Select 
     Output(OutputBufferKey, "Sleeping for " & LengthString) 
    End If 

    If ExitOnTaskStop AndAlso Task IsNot Nothing Then 
     Try 
     Await Tasks.Task.Delay(Milliseconds, Task.CancellationToken.Token) 
     Catch ex As OperationCanceledException 
     Return True 
     End Try 
    Else 
     Await Tasks.Task.Delay(Milliseconds) 
    End If 

    Return False 
    End Function 

J'ai besoin du retard pour de nombreuses raisons et cette méthode est appelée dans un certain nombre d'autres méthodes. Pour donner quelques exemples, j'ai un code qui utilise la DLL OpenPop pour vérifier la réception d'un message dans une boîte de réception, s'il n'est pas là lors de la première vérification, je dois attendre avant de vérifier à nouveau, j'ai la boucle et je dors a été trouvé. Un autre exemple est que je dois faire un HttpWebRequest pour vérifier un fichier, si le contenu n'a pas changé, je veux le faire à nouveau dans 30 secondes. Je suppose que l'utilisation de minuteries serait une meilleure idée? Si oui, quelle est l'utilisation appropriée de Task.Delay?

+0

"J'ai remplacé les threads par des tâches, ensuite je travaille sur le remplacement de mes appels Thread.Sleep avec Await Task.Delay." Pourquoi? – Sam

+0

Pourquoi appelles-tu 'Thread.Sleep'? Si vous l'utilisez dans des endroits aléatoires partout dans le code, vous vous trompez probablement. Séparer la logique métier de la logique de planification des tâches. Et vous n'avez pas vraiment besoin de remplacer tous les appels de Thread.Sleep, mais cela dépend de l'utilisation. – Athari

+0

@Sam La façon dont je le faisais précédemment était de créer des milliers de threads, j'ai été informé en utilisant les tâches était la meilleure façon de le faire. Comme pour Thread.Sleep, Task.Delay semble être une amélioration car je peux lui donner un jeton d'annulation, donc je n'ai pas à Thread.Sleep (100), vérifier l'annulation et boucler à nouveau. Ces questions récentes pourraient mieux expliquer comment j'ai ici. https: // stackoverflow.com/questions/25764970/devrait-je-utiliser-asynchrone-méthodes-dans-un-fond-thread http://stackoverflow.com/questions/25773587/how-do-i-deal-without-byref-in- an-async-function/25773634 – iguanaman

Répondre

1

Les méthodes que vous devez attendre, doivent être marquées asynchrones, pas tout. Si vous avez une fonction simple qui ajoute Var1 + Var2, il serait ridicule de faire cela asynchrone. Cela étant dit, vous finissez par faire beaucoup de choses asynchrones parce qu'ils appellent quelque chose qui appelle quelque chose qui doit être attendu.

Sur la base de la discussion ici, vous pourriez être mieux avec des minuteries qui conduit à votre autre question, « quelle est la bonne utilisation des Task.Delay »? Je l'utilise uniquement pour que je puisse attendre que mon interface utilisateur finisse ce qu'elle est en train de faire. Par exemple, je lance un appel à une base de données et démarre une transformation de l'interface utilisateur pour afficher progressivement une nouvelle partie de l'écran au cours de la prochaine 1/2 seconde. Je ne veux pas remplir mes résultats pendant cette demi-seconde parce que cela crée souvent un écran nerveux alors j'attends que ce soit fait. Le moyen le plus simple est de faire l'appel à la base de données et de créer un délai, puis d'utiliser le WhenAll pour attendre la fin du dernier. C'est généralement ma 1/2 seconde mais parfois la base de données.

Comme une note de côté, vous pouvez appeler des méthodes synchrones utilisant async qui fonctionnent en arrière-plan. C'est une transition beaucoup plus facile de threading mais puisque vous avez déjà changé la plupart de votre code, vous ne voulez pas ici cela.

Questions connexes