简体   繁体   中英

Weird C# Threading ThreadInterrupted exception

I am developing an application simulating a network comprising a number of nodes that exchange messages. I try to simulate the transmission channel with a Queue where every node can place a message. Then, another entity takes over the message and delivers it to the specified node. Then, i want to signal (with an event) the end of a transmission phase when the message queue is idle for a certain amount of time, say X, namely no new messages have been added to the queue for X mseconds.

I understand that my case follows the consumer/producer paradigm. So far, i have done the following:

public class Com<T>
{
    private Thread dispatcher;
    private Queue<T> queue;
    private int waitTime;
    private Object locker;
    private Timer timer;
    public event EventHandler EmptyQueueEvent;

    public Com()
    {
        queue = new Queue<T>();
        locker = new Object();
        waitTime = X;
        timer = new Timer(FireEmpty, null, Timeout.Infinite,Timeout.Infinite);
        dispatcher = new Thread(Serve);
        dispatcher.IsBackground = true;
                    dispatcher.Start();
    }

    private void Serve()
    {
        while (true)
        {
            try
            {
                if (queue.Count == 0)
                {
                    timer.Change(waitTime, 0);
                    Thread.Sleep(Timeout.Infinite);
                }
            }
            catch (ThreadInterruptedException)
            {
            }
            while (queue.Count != 0)
            {
                lock (locker)
                {
                    deliver(queue.Dequeue());
                }
            }
        }
    }

    private void deliver(T item)
    {
        // Do stuff
    }

    public void Add(T item)
    {
        timer.Change(Timeout.Infinite, Timeout.Infinite);
        lock (locker)
        {
            queue.Enqueue(item);
        }
        dispatcher.Interrupt();
    }

    private void FireEmpty(object o)
    {
        //Fire Event
    }
}

However, running my simulations proves that my synchronization is not enough, since I am sometimes getting a "ThreadInterruptedException" while trying to dequeue my message (in method Serve()). Note that the exception does not occur each time i run the simulation, but rather rarely: approximately every 850-1000 executions (i am running the execution iteratively)..

Does anybody have an idea what it is wrong with my code? :)

Have you tried locking before you attempt to get the Queue count? Like:

    private void Serve()
    {
        while (true)
        {
            try
            {
                int count = 0;
                lock(locker)
                   count= queue.Count;
                if (count == 0)
                {
                    timer.Change(waitTime, 0);
                    Thread.Sleep(Timeout.Infinite);
                }
            }
            catch (ThreadInterruptedException)
            {
            }
            while (queue.Count != 0)
            {
                lock (locker)
                {
                    deliver(queue.Dequeue());
                }
            }
        }
    }

It's possible that an add is getting called at the same time you're trying to count the number of items. Also, you might want to consider one of the collections from System.Collections.Concurrent if you're using .net 4.0.

** UPDATE **

I just took a closer look at your code and had an "Oh duh" moment. You should be getting a ThreadInterruptException because you're calling delegate.Interrupt() . Check the MSDN documentation on that. I think what you need to do is use something like a ManualResetEvent and instead of calling Interrupt() do a WaitOne() on that event.

** UPDATE2 ** Here's some sample code that includes my other locking suggestion as well (on Gist): https://gist.github.com/1683547

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM