One shot events using Lambda in C#

c#, events, lambda

Solution

You could attache a permanent event handler to the event. The event handler then invokes "one shot event handlers" that are added to an internal queue:

OneShotHandlerQueue<EventArgs> queue = new OneShotHandlerQueue<EventArgs>();

Test test = new Test();

// attach permanent event handler
test.Done += queue.Handle;

// add a "one shot" event handler
queue.Add((sender, e) => Console.WriteLine(e));
test.Start();

// add another "one shot" event handler
queue.Add((sender, e) => Console.WriteLine(e));
test.Start();

Code:

class OneShotHandlerQueue<TEventArgs> where TEventArgs : EventArgs {
    private ConcurrentQueue<EventHandler<TEventArgs>> queue;
    public OneShotHandlerQueue() {
        this.queue = new ConcurrentQueue<EventHandler<TEventArgs>>();
    }
    public void Handle(object sender, TEventArgs e) {
        EventHandler<TEventArgs> handler;
        if (this.queue.TryDequeue(out handler) && (handler != null))
            handler(sender, e);
    }
    public void Add(EventHandler<TEventArgs> handler) {
        this.queue.Enqueue(handler);
    }
}

Test class:

class Test {
    public event EventHandler Done;
    public void Start() {
        this.OnDone(new EventArgs());
    }
    protected virtual void OnDone(EventArgs e) {
        EventHandler handler = this.Done;
        if (handler != null)
            handler(this, e);
    }
}

Problem

I find myself doing this sort of thing quite often:- ``` EventHandler eh = null; //can't assign lambda directly since it uses eh eh = (s, args) => { //small snippet of code here ((SomeType)s).SomeEvent -= eh; } variableOfSomeType.SomeEvent += eh; ``` Basically I only want to attach an event handler to listen for one shot from the event, I no longer want to stay attached after that. Quite often that "snippert of code" is just one line. My mind is going a bit numb, I'm sure there must be something I can do so I don't need to repeat all this overhead. Bear in mind that `EventHandler` may well be `EventHandler<T>`. Any ideas how I can tidy up the repeative part of the code and just leave the snippet in a Lambda?

Original source

Related problems