Я хотел бы использовать переменную условия, чтобы знать, когда очередь сообщений не пуста, я хотел бы использовать ее в "HandleMessageQueue" в качестве потока - PullRequest
0 голосов
/ 20 декабря 2018

Я хотел бы использовать Условную переменную, чтобы знать, когда очередь сообщений не пуста, я хотел бы использовать ее в "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 голосов
/ 20 декабря 2018

То, что вы, вероятно, ищете, - это простая модель производитель-потребитель.В этом случае я бы порекомендовал использовать .NET BlockingCollection, что позволяет легко обрабатывать следующие случаи:

  1. иметь один поток push-материала в очереди
  2. иметь другой потокблокировать, пока материал не станет доступным
  3. сделать все это простым, чтобы отключить его без принудительного завершения потокаhas:
    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>делает).

0 голосов
/ 20 декабря 2018

как то так?

 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...