我想使用条件变量以便知道Messages Queue何时不为空,我想在“ HandleMessageQueue”中将其用作线程

时间:2018-12-20 17:50:08

标签: c# .net thread-safety condition-variable

我想使用条件变量来了解Messages Queue何时不为空,我想在“ HandleMessageQueue”中将其用作线程

private static Queue<Message> messages = new Queue<Message>();

/// <summary>
/// function return the first message
/// </summary>
/// <returns>first message element</returns>
public static Message GetFirst()
{
  return messages.Dequeue();
}

在另一个班级:

/// <summary>
/// Function run while the clients connected and handle the queue message
/// </summary>
public static void HandleMessageQueue()
{
   // ...
}

2 个答案:

答案 0 :(得分:0)

像这样吗?

 public class EventArgs<T> : EventArgs
{
    private T eventData;


    public EventArgs(T eventData)
    {
        this.eventData = eventData;
    }


    public T EventData
    {
        get { return eventData; }
    }
}
public class ObservableQueue<T>
{
    public event EventHandler<EventArgs<T>> EnQueued;
    public event EventHandler<EventArgs<T>> DeQueued;
    public int Count { get { return queue.Count; } }

    private readonly Queue<T> queue = new Queue<T>();

    protected virtual void OnEnqueued(T item)
    {
        if (EnQueued != null)
            EnQueued(this, new EventArgs<T>(item));
    }

    protected virtual void OnDequeued(T item)
    {
        if (DeQueued != null)
            DeQueued(this, new EventArgs<T>(item));
    }

    public virtual void Enqueue(T item)
    {
        queue.Enqueue(item);
        OnEnqueued(item);
    }

    public virtual T Dequeue()
    {
        var item = queue.Dequeue();
        OnDequeued(item);
        return item;
    }
}

并使用它

   static void Main(string[] args)
    {

        ObservableQueue<string> observableQueue = new ObservableQueue<string>();
        observableQueue.EnQueued += ObservableQueue_EnQueued;
        observableQueue.DeQueued += ObservableQueue_DeQueued;
        observableQueue.Enqueue("abc");
        observableQueue.Dequeue();

        Console.Read();
    }

答案 1 :(得分:0)

您可能正在寻找的是一种简单的生产者-消费者模式。在这种情况下,我建议使用.NET的BlockingCollection,它使您可以轻松处理以下情况:

  1. 只有一个线程将内容推送到队列中
  2. 还有另一个线程块,直到可用为止
  3. 使整个事情很容易关闭,而不必强行终止线程

这是一个简短的代码示例,请阅读注释以获取有关每一位操作的更多信息:

public class Queue : IDisposable
{
    private readonly Thread _messageThread; // thread for processing messages
    private readonly BlockingCollection<Message> _messages; // queue for messages
    private readonly CancellationTokenSource _cancellation; // used to abort the processing when we're done

    // initializes everything and starts a processing thread
    public Queue()
    {
        _messages = new BlockingCollection<Message>();
        _cancellation = new CancellationTokenSource();

        _messageThread = new Thread(ProcessMessages);
        _messageThread.Start();
    }

    // processing thread function
    private void ProcessMessages()
    {
        try
        {
            while (!_cancellation.IsCancellationRequested)
            {
                // Take() blocks until either:
                // 1) a message is available, in which case it returns it, or
                // 2) the cancellation token is cancelled, in which case it throws an OperationCanceledException

                var message = _messages.Take(_cancellation.Token); 
                // process the message here
            }
        }
        catch (OperationCanceledException)
        {
            // Take() was cancelled, let the thread exit
        }
    }

    // pushes a message
    public void QueueMessage(Message message)
    {
        _messages.Add(message);
    }

    // stops processing and clean up resources
    public void Dispose()
    {
        _cancellation.Cancel(); // let Take() abort by throwing
        _messageThread.Join(); // wait for thread to exit
        _cancellation.Dispose(); // release the cancellation source
        _messages.Dispose(); // release the queue
    }
}

另一种选择是将ConcurrentQueue<T>ManualResetEvent组合在一起(事件大致相当于条件变量的.NET),但这是手动完成的BlockingCollection<T>