Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I wait for a C# event to be raised?

Tags:

c#

events

I have a Sender class that sends a Message on a IChannel:

public class MessageEventArgs : EventArgs {
  public Message Message { get; private set; }
  public MessageEventArgs(Message m) { Message = m; }
}

public interface IChannel {
  public event EventHandler<MessageEventArgs> MessageReceived;
  void Send(Message m);
}

public class Sender {
  public const int MaxWaitInMs = 5000;
  private IChannel _c = ...;

  public Message Send(Message m) {
    _c.Send(m);
    // wait for MaxWaitInMs to get an event from _c.MessageReceived
    // return the message or null if no message was received in response
  }
}

When we send messages, the IChannel sometimes gives a response depending on what kind of Message was sent by raising the MessageReceived event. The event arguments contain the message of interest.

I want Sender.Send() method to wait for a short time to see if this event is raised. If so, I'll return its MessageEventArgs.Message property. If not, I return a null Message.

How can I wait in this way? I'd prefer not to have do the threading legwork with ManualResetEvents and such, so sticking to regular events would be optimal for me.

like image 851
Evan Barkley Avatar asked May 12 '10 16:05

Evan Barkley


1 Answers

Use a AutoResetEvent.

Gimme a few minutes and I'll throw together a sample.

Here it is:

public class Sender
{
    public static readonly TimeSpan MaxWait = TimeSpan.FromMilliseconds(5000);

    private IChannel _c;
    private AutoResetEvent _messageReceived;

    public Sender()
    {
        // initialize _c
        this._messageReceived = new AutoResetEvent(false);
        this._c.MessageReceived += this.MessageReceived;
    }

    public Message Send(Message m)
    {
        this._c.Send(m);
        // wait for MaxWaitInMs to get an event from _c.MessageReceived
        // return the message or null if no message was received in response


        // This will wait for up to 5000 ms, then throw an exception.
        this._messageReceived.WaitOne(MaxWait);

        return null;
    }

    public void MessageReceived(object sender, MessageEventArgs e)
    {
        //Do whatever you need to do with the message

        this._messageReceived.Set();
    }
}
like image 200
Toby Avatar answered Sep 28 '22 06:09

Toby