2010-07-30 14 views
2

J'ai travaillé sur la mise en place d'un accélérateur pour limiter le nombre de messages envoyés. Bien que cela fonctionne, je suis curieux de savoir s'il existe un meilleur moyen? Tout conseil est apprécié.Révision de code (première tentative de multithreading)

public Class MyApp 
{ 
    private long _messagesSent; 
    private long _totalMessagesSent; 

    public int NumberOfMessages { get; set; } 
    public int MessagesPerSecond { get; set; } 

    public void SendMessage() 
    { 
     ThreadholdMonitor.Start(); 

     for (var i = 0; i < NumberOfMessages; i++) { 
      // Code here... 

     if (MessagesPerSecond <= _messagesSent) { 
      ThreadholdMonitor.StopSendingEvent.Set(); 

      lock (this) { 
       var hasPrinted = false; 
       while (ThreadholdMonitor.StopSendingEvent.WaitOne(0, false)) { 
        if (hasPrinted == false) { 
         Console.WriteLine("Sent " + _messagesSent + " messages"); 
         hasPrinted = true; 
        } 

        Interlocked.Exchange(ref _messagesSent, 0); 
       } 
      } 
     } 

     SendMessage(details); 
     Interlocked.Increment(ref _messagesSent); 
     Interlocked.Increment(ref _totalMessagesSent); 

     } 

     ThreadholdMonitor.Stop(); 
    } 
} 

public class ThreadholdMonitor 
{ 
    private static ManualResetEvent _monitorEvent; 

    public static ManualResetEvent StopSendingEvent { get; set; } 

    public static void Start() 
    { 
     _monitorEvent = new ManualResetEvent(false); 
     StopSendingEvent = new ManualResetEvent(false); 

     Thread monitorThread = new Thread(new ThreadStart(ControlSharedSignal)); 
     monitorThread.Start(); 
    } 

    public static void Stop() 
    { 
     _monitorEvent.Set(); 
    } 

    private static void ControlSharedSignal() 
    { 
     var startTime = DateTime.Now; 

     while (_monitorEvent.WaitOne(0, false) == false) { 
      if (DateTime.Now.Subtract(startTime).Seconds >= 1) { 
       StopSendingEvent.Reset(); 
       startTime = DateTime.Now; 
      } 
     } 
    } 
} 
+1

Il y a trop de code et pas assez de commentaires. Veuillez expliquer ce que ce code essaie de faire. –

+1

Nonsense, vous n'avez pas besoin de commentaires. Mais vous avez besoin d'un code qui peut être lu et compris sans commentaires si vous n'allez pas les avoir. Ce qui est ce que vous devriez avoir de toute façon. –

+0

Mes excuses si c'est illisible ... c'était ma première tentative. :( – Ryan

Répondre

1

Utilisez un sémaphore. La meilleure façon de le faire est avec un sémaphore. Cela fournira la manette des gaz et l'attente automatique en même temps.

3

Ne faites pas cela. Ça n'a pas l'air bien. Mais surtout, vous ne serez jamais sûr qu'un problème que vous rencontrerez plus tard n'est pas causé par ce code. Et vous avez besoin de toute l'aide possible pour diagnostiquer les races de threads inévitables que vous rencontrerez tôt ou tard. Le type de bugs vraiment merdique, ceux qui frappent seulement une fois de temps en temps et ne reprennent jamais lorsque vous essayez de déboguer le problème. Moins le code peut être la source d'un tel problème, mieux c'est.

Vous avez marqué cela avec C# 4.0, l'infrastructure .NET 4.0 a d'excellentes classes dans l'espace de noms System.Collections.Concurrent. La classe BlockingCollection a été créée pour faire ce que vous essayez de faire. Il a non seulement été vérifié et testé à l'infini pour ne jamais être soumis à des courses de threads, il a été conçu pour ne pas souffrir des problèmes de threads durs. Comme l'impasse, la famine, l'inversion de priorité, les convois de verrouillage. Le genre de merde qui te fait perdre tes cheveux.

Désistement: Il ne me reste plus beaucoup de cheveux.

+0

Je savais que ça n'avait pas l'air bien, c'est pourquoi je l'ai posté ici Merci pour votre suggestion, Je suis vraiment nouveau dans le threading donc je ne suis pas familier avec la classe blockingCollection mais je vais y réfléchir. – Ryan