79527694

Date: 2025-03-22 16:03:51
Score: 1
Natty:
Report link

A big thanks to @ Marc Gravell for his example. I was using a ConcurrentQueue<T> for cross-thread access between my library and Forms project.

Before seeing Marc's example, I was using a Timer to 'dequeue the queue' on the GUI thread. So following the example, I made a CustomConcurrentQueue<T> for thread safety. The CustomConcurrentQueue<T> also triggers an event when a new message is added to the Queue. The example below uses the event to add text to a textbox.

/// <summary>
/// Courtesy of Marc Gravell https://stackoverflow.com/questions/531438/c-triggering-an-event-when-an-object-is-added-to-a-queue
/// Allows event handling to notify if an object of type T has been enqueued or dequeued
/// </summary>
/// <typeparam name="T"></typeparam>
public class CustomConcurrentQueue<T>
{
    private readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();

    public event EventHandler Changed;

    public event EventHandler Enqueued;

    protected virtual void OnChanged()
    {
        if (Changed != null) Changed(this, EventArgs.Empty);
    }

    protected virtual void OnEnqueued()
    {
        if (Enqueued != null) Enqueued(this, EventArgs.Empty);
    }

    public virtual void Enqueue(T item)
    {
        queue.Enqueue(item);
        OnChanged();
        OnEnqueued();
    }
    public int Count { get { return queue.Count; } }

    public virtual bool TryDequeue(out T item)
    {
        if (queue.TryDequeue(out item))
        {
            OnChanged();
            return true;
        }

        return false;
    }
}

With an example of how I used it in a Form:


public CustomConcurrentQueue<string> MyMessages { get; set; }

MyMessages = new CustomConcurrentQueue<string>();

MyMessages.Enqueued += new new System.EventHandler(this.OnNewMessages);

//MyMessages.Enqueue("Hello World!");

private void OnNewMessages(object sender, EventArgs e)
{
    if (MyMessages == null) return;

    while (MyMessages.Count > 0)
    {
        var str = "";

        if (MyMessages.TryDequeue(out str))
        {
            //Example: Append 'Hello World!' to the textbox on GUI thread...
            Invoke((Action)(() =>
            {
                //this.textBox1.AppendText(Environment.NewLine + $"{str}");
            }));
        }
    }
}

Reasons:
  • Blacklisted phrase (0.5): thanks
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Seven7