奇怪的C#Threading ThreadInterrupted异常

时间:2012-01-26 14:53:26

标签: c# multithreading

我正在开发一个模拟网络的应用程序,该网络包含许多交换消息的节点。我尝试使用Queue模拟传输通道,其中每个节点都可以发送消息。然后,另一个实体接管消息并将其传递到指定节点。然后,我希望在消息队列空闲一段时间(例如X)时发信号通知(带有事件)传输阶段的结束,即没有新的消息添加到队列中为X毫秒。

据我所知,我的案例遵循消费者/制作人范例。到目前为止,我已经完成了以下工作:

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
    }
}

然而,运行我的模拟证明我的同步是不够的,因为我有时在尝试使我的消息出队时得到“ThreadInterruptedException”(在方法Serve()中)。请注意,每次运行模拟时都不会发生异常,而是很少发生:大约每850-1000次执行(我正在迭代地执行执行)..

有人知道我的代码有什么问题吗? :)

1 个答案:

答案 0 :(得分:1)

在尝试获取Queue计数之前,您是否尝试过锁定?像:

    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());
                }
            }
        }
    }

在您尝试计算项目数量的同时,可能会调用添加项。此外,如果您使用.net 4.0,则可能需要考虑System.Collections.Concurrent中的一个集合。

** 更新 **

我只是仔细看看你的代码,并有一个“哦呃”的时刻。您应该收到ThreadInterruptException,因为您正在呼叫delegate.Interrupt()。检查MSDN documentation。我认为你需要做的就是使用类似ManualResetEvent的内容,而不是在Interrupt()上调用WaitOne()

** UPDATE2 ** 这里有一些示例代码,包括我的其他锁定建议(在Gist上): https://gist.github.com/1683547