0

I want to subscribe and unsubscribe from a ToolStripButton's Click event using a globally declared delegate as discribed in this SO question and subsequent answers. I have the following delegate declared globally in my class

private delegate void StopTask(ref MainForm _mainForm, 
    Task _task, CancellationTokenSource _cancelSource);

I then set this delegate to hold a method as follows

StopTask cancelTask = UtilsTPL.CancelRunningProcess;

where in the public class UtilsTPL, CancelRunningProcess is defined as

public static void CancelRunningProcess(ref MainForm _mainForm, Task _task, 
    CancellationTokenSource _cancelSource)
{
    // Some really amazing code...
}

I then try to add the delegate to my ToolStripButton click event like this (and also unsubscribe as shown)

mainForm.stopButton.Click += cancelTask;
mainForm.stopButton.Click -= cancelTask;

This clearly does not work, as there is a glaring type miss-match.

How do I subscribe/unsubscribe the consistant delegate cancelTask to the buttons click event? Thanks for your time.

Note: I am doing this so that the button can be reused for the cancellation of many different Tasks.

Community
  • 1
  • 1
MoonKnight
  • 23,214
  • 40
  • 145
  • 277

2 Answers2

2

Instead of subscribing and unsubscribing from the click event, call your cancelTask from your click-event

private void stopButton_Click(object sender, EventArgs e)
{
    var handler = cancelTask;
    if (handler != null) {
        handler(this, _task, _cancelSource);
    }
}

and subscribe and unsubscribe from cancelTask

cancelTask += Whatever;
cancelTask -= Whatever;
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • This should be `handler(ref this, _task, _cancelSource)` to match the delegate type, and typing `ref this` sends shivers down my spine. – Frédéric Hamidi Mar 13 '12 at 21:46
  • Yes, the MainForm is a reference type; therefore, the argument should probably not be `ref` anyway. Probably it would not work with multicast delegates either. – Olivier Jacot-Descombes Mar 13 '12 at 21:56
  • So you are saying that this would not work? I can't see the wood-for-the-trees at the moment - it has been a long day. Any further suggestion would be appreciated. – MoonKnight Mar 13 '12 at 22:03
  • A `ref` parameter means that a reference to the original variable is passed to the method. The method can therefore change the value of this original variable (not just the properties of an object referenced by this variable). With a multicast delegate, multiple methods can be "attached" to the delegate and therefore multiple methods could try to change the value of this single variable. Which one of them would win? And by the way, what would happen if you changed `this` (see Frédéric Hamidi's comment)? – Olivier Jacot-Descombes Mar 13 '12 at 22:22
  • If you pass MainForm as parameter to a method, this method can change public properties of MainForm, even if the parameter is not a `ref` parameter. Because the form is a reference type, a reference is passed anyway. With `ref`, a reference to this reference would be passed, which is probably not what you intended. – Olivier Jacot-Descombes Mar 13 '12 at 22:29
0

I'd be a bit more curious about what you are trying to accomplish. Perhaps there is a way to do things without using a global multi-cast delegate.

Joel B
  • 801
  • 1
  • 11
  • 30