排队操作

时间:2010-12-30 15:08:08

标签: c# multithreading

即时通过dll发送smses,dll有一些事件,一个是

Session_OnMessageAccepted

里面我正在做这样的事情

   void Session_OnMessageAccepted(object sender,EventArgs e)
     {
         new Thread(
             delegate()
                 {
                     //do stuff
                 }).Start();
     }

这是好的唯一的问题是dostuff里面的代码同时被执行了,有没有机会我可以将“dostuff”放入队列中并使其同步发生?

3 个答案:

答案 0 :(得分:0)

您正在寻找ConcurrentQueue class

答案 1 :(得分:0)

您可以在队列中添加消息。您可以启动一个单独的线程(On App Start),它将不断查找队列中的消息并进行处理。

即在线程方法

while(true)
{
    //check if the queue is empty otherwise continue;
    //fetch the element
    //process it
}

答案 2 :(得分:0)

  

关于ThreadPool的注释

作为对当前代码的一般性评论,请考虑使用ThreadPool.QueueUserWorkItem而不是创建新线程。

将工作项排队到ThreadPool比为短期任务创建新线程更有效。 ThreadPool维护现有线程池并重新使用它们。创建和管理线程很昂贵,因此在需要许多短期任务时应该避免使用。除了有效率之外,ThreadPool也具有自然排队行为。

但是,使用ThreadPool并不能保证项目按照您排队的顺序执行,也可能导致项目同时执行,即同时执行。因此,ThreadPool并没有帮助你解决这个问题。

  

示例消息处理循环

以下是一个消息处理循环模式,它允许对操作进行排队,然后在一个单独的线程上进行串行处理。

public class SomeClass
{
    private readonly object _syncObj = new object();
    private readonly Thread _thread;
    private readonly Queue<Action> _queue = new Queue<Action>();
    private readonly ManualResetEvent _messageAccepted = new ManualResetEvent(false);

    public SomeClass()
    {
        _thread = new Thread(() =>
        {
            while (true)
            {
                Action operation;

                while (TryDequeue(out operation))
                {
                    operation();
                }

                _messageAccepted.WaitOne();
            }
        }) {IsBackground = true};

        _thread.Start();
    }

    private void Session_OnMessageAccepted(object sender, EventArgs e)
    {
        Action operation = () =>{/* Do stuff */};

        Enqueue(operation);
    }

    private void Enqueue(Action operation)
    {
        lock (_syncObj)
        {
            _queue.Enqueue(operation);

            _messageAccepted.Set();
        }
    }

    private bool TryDequeue(out Action operation)
    {
        lock (_syncObj)
        {
            operation = (_queue.Count != 0) ? _queue.Dequeue() : null;

            if (operation == null) _messageAccepted.Reset();

            return (operation != null);
        }
    }
}