views:

151

answers:

2

Ive been working on setting up a throttle to limit the number of messages sent. Although this works, Im curious if there is a better way? Any advice is appreciated.

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  A: 

Use a semaphore. The best way to do this is with a semaphore. This will provide the throttle and the automatic wait at the same time.

Mike
+2  A: 

Don't do this. It doesn't look good. But most of all, you'll never be sure that some kind of problem you'll have later isn't caused by this code. And you need all the help you can get to diagnose the inevitable threading races you'll run into sooner or later. The really crappy kind of bugs, those that strike only once in a while and never repro when you try to debug the issue. The less code that can be the source of such a problem, the better.

You tagged this with C# 4.0, the .NET 4.0 framework has excellent classes in the System.Collections.Concurrent namespace. The BlockingCollection class was made to do what you're trying to do. It hasn't just been verified and endlessly tested to never be subject to threading races, it has been engineered to not suffer from the hard threading problems. Like deadlock, starvation, priority inversion, lock convoys. The kind of crap that makes you lose your hair.

Disclaimer: I don't have a lot of hair left.

Hans Passant
I knew it didnt look good which is why I posted it here. Thank you for your suggestion, Im really new to threading so Im not familiar with the blockingCollection class but I will look into it, thanks.
Farstucker