Adjit
Adjit

Reputation: 10305

Understanding event handling for incoming messages

I am trying to understand a portion of code from the Interactive Brokers sample in their API. It is about processing data from incoming messages, and while I understand the general flow of event handling, I don't understand this one part:

ibClient.ScannerData += (reqId, rank, contractDetails, distance, benchmark, projection, legsStr) => 
    HandleMessage(new ScannerMessage(reqId, rank, contractDetails, distance, benchmark, projection, legsStr));

What is happening in this line of code? I understand what is going on in the grander scheme of things, but not what is happening with the ibClient.ScannerData += ([params]) => f(g([params]))

The HandleMessage method is responsible for obviously handling incoming messages, and since this line of code is only run once, I believe this is telling ibClient.ScannerData information how to handle ScannerData information that is sent to ibClient.

This is what ibClient looks like in the backend -

public event Action<int, int, ContractDetails, string, string, string, string> ScannerData;

void EWrapper.scannerData(int reqId, int rank, ContractDetails contractDetails, string distance, string benchmark, string projection, string legsStr)
{
    var tmp = ScannerData;

    if (tmp != null)
        tmp(reqId, rank, contractDetails, distance, benchmark, projection, legsStr);
}

Where EWrapper.scannerData is -

void  scannerData (int reqId, int rank, ContractDetails contractDetails, string distance, string benchmark, string projection, string legsStr)

provides the data resulting from the market scanner request.

Upvotes: 0

Views: 352

Answers (2)

CodingYoshi
CodingYoshi

Reputation: 27039

That is basically assigning an event handler to an event. Let's look at a simpler example with less parameter to help clarify the confusion. If you look at the Button class, it has a click event and the signature for the event is like this:

public delegate void EventHandler(object sender, EventArgs e);

So basically to subscribe to the Click event of the button, you need a method which takes an object and an EventArgs. So to subscribe to it you do this:

button.Click += new EventHandler(Button_Click);

Or this:

button.Click += (se, ev) => Button_Click(sender, e);

Or even short, you can do this:

button.Click += Button_Click;

They are all doing the same. They are saying when the button's Click event is fired, call the Button_Click method. The method looks like this:

private void Button_Click(object sender, EventArgs e)
{
    // code here
}

The += is subscribing, or adding a handler to the Click event. You can add as many as you want. If you want to unsubscribe or remove the handler, you use -=.

In your case, the event is like this:

public event Action<int, int, ContractDetails, string, string, string, string> ScannerData;

So it is saying to subscribe to the ScannerData event, you need a method which takes 7 parameters (2 ints, a ContractDetails and 4 strings). So to subscribe to it, you do this:

ibClient.ScannerData += (reqId, rank, contractDetails, distance, benchmark, projection, legsStr) => 
    HandleMessage(new ScannerMessage(reqId, rank, contractDetails, distance, benchmark, projection, legsStr));

The Action delegate:

Encapsulates a method that has a single parameter and does not return a value.

In your case it is an Action delegate with more parameters.

This => is a lambda notation. Essentially it could have been like this:

this.ScannerData += new Action<int, int, ContractDetails, string, string, string, string>(
    HandleMessage
    (new ScannerMessage(reqId, rank, contractDetails, distance, 
                        benchmark, projection, legsStr));

You can read this article or google event hanlders with lambda and there are plenty of articles.

Upvotes: 2

laser
laser

Reputation: 570

ibClient.ScannerData is a list of event.

This adds a new event to the list:

ibClient.ScannerData += (reqId, rank, contractDetails, distance, benchmark, projection, legsStr) => 
    HandleMessage(new ScannerMessage(reqId, rank, contractDetails, distance, benchmark, projection, legsStr));

This takes event list, and make a call to all registered events:

var tmp = ScannerData;

if (tmp != null)
    tmp(reqId, rank, contractDetails, distance, benchmark, projection, legsStr);

Found some explanation on += operation on function: += new EventHandler(Method) vs += Method

Upvotes: 0

Related Questions