Ruudster
Ruudster

Reputation: 157

Passing data with events

I need to pass data with an event. Currently, when receiving more data (via comport), the event will fire but the previous event (&data) is not handled yet, so the data gets overwritten.
How can I handle the event &data in a safe way? I have multiple events like this (15x), so I am not sure if using a queue for the data is the best way or pass data along with the event (like S.O. item 4215845).

Example (this example is with a string, but I also use arrays, bools etc):

At the 'sender' side (class1):

public event EventHandler evDiaStringMessage = delegate { };
private void evDiaStringMessageEvent()
{
    evDiaStringMessage(this, new EventArgs());
}
private static string _DiaString;
public string DiaString
{
    get { return _DiaString; }
    set { _DiaString = value; }
}

DiaString contains the data and gets overwritten when evDiaStringMessage is fired too soon.

At the 'receiver / GUI' side (class2):

dia.evDiaStringMessage += new EventHandler(dia_evDiaStringMessage);

private delegate void dia_evDiaStringMessageCallBack(object sender, EventArgs e);
void dia_evDiaStringMessage(object sender, EventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new dia_evDiaStringMessageCallBack(dia_evDiaStringMessage), new object[] { sender, e});
    }
    else
    {
        frmcomm.CommTextBox("Receiver message: " + dia.DiaString + "\r\n", Color.Red);
    }
}

dia.DiaString does not contain the expected data (previous data), but all events are 'received'.

Your help is very much appreciated! Even more with an example!

Edit:

I changed the code to:

At the 'sender' side (class1):

public event EventHandler<DiaStringEventArgs> evDiaStringMessage ;
public class DiaStringEventArgs : EventArgs
{
    public string DiaString  { get; set; }
}

private void evDiaStringMessageEvent(DiaStringEventArgs e)
{
    EventHandler<DiaStringEventArgs> handler = evDiaStringMessage;
    if (handler != null)
        handler(this, e);
}

...

private void PrepareDataAndFireEvent()
{
    DiaStringEventArgs args = new DiaStringEventArgs(); 
    args.DiaString = ByteToString(data);
    evDiaStringMessageEvent(args);
}

At the 'receiver / GUI' side (class2):

dia.evDiaStringMessage += new EventHandler<ifDiA10.DiaStringEventArgs>(dia_evDiaStringMessage);

private delegate void dia_evDiaStringMessageCallBack(object sender, ifDiA10.DiaStringEventArgs e);
void dia_evDiaStringMessage(object sender, ifDiA10.DiaStringEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new dia_evDiaStringMessageCallBack(dia_evDiaStringMessage), new object[] { sender, e});
    }
    else
    {
        frmcomm.CommTextBox("Receiver message: " + e.DiaString + "\r\n", Color.Red);
    }
}

Upvotes: 15

Views: 22337

Answers (2)

user27414
user27414

Reputation:

You can store your data in a custom EventArgs class:

public class ReceivedDataEventArgs : EventArgs
{
   // Add the properties you require
}

The event is defined like so:

public event EventHandler<ReceivedDataEventArgs> ReceivedData;

Your handler will take in an instance your class instead of the EventArgs object, and hence you'll have the correct data.

Upvotes: 20

Kami
Kami

Reputation: 19407

You should pass the value of dia.DiaString when the event is raised rather than reading it back when the event is handled.

You can do this by extending the EventArgs class and creating custom properties.

If you need an example let me know.

Upvotes: 2

Related Questions