Question

Suppose I have an event indicating that some data is received:

public event<DataEventArgs> EventHandler SomeDataReceived;
protected virtual void OnSomeDataReceived(DataEventArgs e)
{
    EventHandler handler = SomeDataReceived;
    if (handler != null)
    {
        handler(this, e);
    }
}

And I have an event handler that handles it:

private void m_SomeDataReceived(object sender, DataEventArgs e)
{
    ... //handling received data
}

Now suppose there are some devices that send me data messages randomly. And one time I receive a message while m_SomeDataReceived delegate's code is being executed. I mean what happens with handling when events occur almost simultaneously? Are handlers executed in parallel in such cases or one has to wait before the other is executed?

Was it helpful?

Solution

Yes and no. If the event occures on the same thread one runs after each other, but if e.g. every device runs on its own thread the event handlers can also execute in paralell.

Events are not different in that matter than normal methods. If you want to make shure they are NOT executed in paralell either use locking:

private void m_SomeDataReceived(object sender, DataEventArgs e)
{
    lock (SyncRoot)
    {
        ... //handling received data
    }
}

Or bring them on the same thread:

protected virtual void OnSomeDataReceived(DataEventArgs e)
{
    EventHandler handler = SomeDataReceived;
    if (handler != null)
    {
        CONTEXT.Invoke(() => handler(this, e)); // context can e.g. be a Dispatcher from a WPF control
    }
}

In this case it still CAN HAPPEN that the second call starts before the first one finishes if the handling gives up the thread (e.g. Application.DoEvents() or await Task.Delay())!

If the events are generated in the same thread and you want them to be executed in paralell you can do something like the following:

public static void RaiseAsync<T>(this EventHandler<EventArgs<T>> theEvent, object sender, T args)
{
    if (theEvent != null)
    {
        var eventArgs = new EventArgs<T>(args);
        foreach (EventHandler<EventArgs<T>> action in theEvent.GetInvocationList())
            action.BeginInvoke(sender, eventArgs, null, null);
    }
}

Then instead of calling OnSomeDataReceived you can simply call SomeDataReceived.RaiseAsync(this, args).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top