2017-07-17 1 views
1

Considérons que j'ai un écouteur d'événement en C# qui attend les données du port série, qui sont renvoyées une fois capturées en définissant un statut. Dans la boucle principale, je regarde dans ce statut et sur cette base, je décide quoi faire ensuite. Pour ce faire, j'écris d'abord la commande dans le port série et j'attends la sortie en utilisant la méthode Thread.Sleep. Au moment où le thread principal est toujours en mode veille, l'écouteur d'événement enverra déjà les données et rien n'est fait pour gérer ce scénario.Gestion des données envoyées par les gestionnaires d'événements en mode veille du thread principal C#

Quelqu'un peut-il s'il vous plaît me dire quel serait le résultat dans cette condition et comment l'éviter?

Le code serait comme

bool status = false; 
//main thread 
private void Main() 
{ 

    //some Code 
    serialPort.Write("something"); 

    //Wait for 10 sec 
    Thread.Sleep(10000); 
    while(status == false) 
    { 
     // do something else 
    } 
} 


    //Ignore the syntax, this is just to make people understand 
    public void OndataReceived(object sender, EventArg arg) 
    { 
     //Function that recieve the data 
     Receive(); 

     //change status to true 
     status = true; 

     return; 
    } 
+1

Jetez un oeil à Manuel- et AutoResetEvent – Dawnkeeper

+0

créer votre événement personnalisé, le feu de l'intérieur de la méthode 'OndataReceived' et faire les prochaines étapes de la méthode à mon avis –

Répondre

0

La question est formulée gauchement, mais si je comprends bien, vous demandez comment vous pouvez éviter d'attendre dix secondes si les données sont reçues plus tôt que cela.

Il est possible d'utiliser des objets de synchronisation plus anciens, tels que l'une des sous-classes WaitHandle, Monitor ou même un sémaphore. Mais pour ce type de scénario, l'idiome C# actuel doit utiliser TaskCompletionSource, ce qui fournit à la fois un objet waitable et l'option de retourner une valeur de résultat en même temps.

Par exemple:

TaskCompletionSource<bool> _result; 

//main thread 
private void Main() 
{ 

    //some Code 
    serialPort.Write("something"); 

    _result = new TaskCompletionSource<bool>(); 

    // Normally, one should "await" a Task. But in the Main() method, which 
    // cannot be "async", we have to just wait synchronously. 
    Task completed = Task.WhenAny(_result.Task, 
     Task.Delay(TimeSpan.FromSeconds(10)).Result; 

    // Don't check "_result.Result" unless the task has completed, 
    // because otherwise the thread will block. If it is completed, 
    // check "_result.Result" as the equivalent to examining the "status" 
    // variable in the previous code example. 
    while(!_result.IsCompleted || !_result.Result) 
    { 
     // do something else 
    } 
} 

public void OndataReceived(object sender, EventArg arg) 
{ 
    //Function that recieve the data 
    Receive(); 

    //change status to true 
    _result.SetResult(true); 

    return; 
} 
+0

Merci Peter. Oui, je veux dire la même chose. Mais dans mon cas, si les données sont envoyées lorsque le thread principal, qui est démarré en Thread.Start (Main), est en mode veille, tout le service Windows se bloque, alors peut-être que votre réponse m'aiderait dans cela. Et encore une chose, j'ai beaucoup d'endroits où Thread.Sleep est utilisé, sera-t-il sûr d'utiliser le nouvel objet Task à la place? –

+0

_ "J'ai beaucoup d'endroits où Thread.Sleep est utilisé, sera-t-il sûr d'utiliser le nouvel objet Task à la place?" _ - Partout où vous avez 'Thread.Sleep()', vous devriez vraiment chercher d'autres implémentations (telles que comme ci-dessus). La méthode 'Thread.Sleep()' n'a jamais été un très bon moyen de retarder le traitement car elle bloque le thread dans lequel elle est appelée, et le C# moderne a de bien meilleurs moyens d'obtenir le même résultat. –