Adjit
Adjit

Reputation: 10305

Action Delegation in C#

I am reviewing some code from a sample application for an API, and need some help better understanding the Action<T> delegation throughout the sample app. I have put several questions throughout the code. Any help is appreciated

The API is implemented in the Client.cs class, and when I make requests from the application, the API sends the responses to the functions in Client.cs that have been implemented.

/*****  Client.cs  *****/

public event Action<int, int, int> TickSize;

void tickSize(int tickerId, int field, int size)
{
    var tmp = TickSize;

    //What is the point of tmp, and why do we check if it is not null?

    if (tmp != null)
        //This invokes the Action? ie - fires the TickSize Action event?
        tmp(tickerId, field, size);
}

Then the UI.cs class handles the UI interactions and feeding the information back into the UI so the user can see what data is returned

/*****  UI.cs  *****/

//Delegate to handle reading messages
delegate void MessageHandlerDelegate(Message message);

protected Client client;

public appDialog(){
    InitializeComponent();
    client = new Client();
    .
    .
    //Subscribes the client_TickSize method to the client.TickSize action?
    client.TickSize += client_TickSize;
}

void client_TickSize(int tickerId, int field, int size){
    HandleMessage(new Message(ticketID, field, size));
}

public void HandleMessage(Message message){
    //So, this.InvokeRequired checks if there is another thread accessing the method?
    //Unclear as to what this does and its purpose
    //What is the purpose of the MessageHandlerDelegate callback
    // - some clarification on what is going on here would be helpful
    if (this.InvokeRequired)
        {
            MessageHandlerDelegate callback = new MessageHandlerDelegate(HandleMessage);
            this.Invoke(callback, new object[] { message });
        }
        else
        {
            UpdateUI(message);
        }

}

private void UpdateUI(Message message) { handle messages }

Upvotes: 0

Views: 114

Answers (1)

JohanP
JohanP

Reputation: 5472

From the docs

Events are a special kind of multicast delegate that can only be invoked from within the class or struct where they are declared (the publisher class). If other classes or structs subscribe to the event, their event handler methods will be called when the publisher class raises the event

So in Client.cs you have a multicast delegate called TickSize. This delegate enables other classes to subscribe to the event it is associated with. So in your function void tickSize(int tickerId, int field, int size), you want to let all the other subscribers know that a tick event has happened.

To do this, you first see if you have any subscribers. This is where the null check happens in if (tmp != null). Having tmp is not needed, you could have done if(TickSize != null) If you have any eventhandlers registered, it would fire and subscribers will receive that call. In your case, you do have subscribers because you are subscribing to the event in public AppDialog with this code : client.TickSize += client_TickSize;

So whenever void tickSize(...) is called in Client.cs, the code in void client_TickSize(...) will run. This will call HandleMessage which will check if it needs to be called by an Invoke function because calling code is not on UI thread. If it does need to be called using Invoke, it will then call the same message using current Control's Invoke function (Not sure which control, could be Form). The HandleMessage will then see that Invoke is not required because caller is on UI thread and then it will call UpdateUi which will update controls.

Upvotes: 1

Related Questions