I mentioned the Action delegate in a session I did at Tech Ed EMEA recently and it seems not many people are using it or are aware that it even exists, hopefully this post should change that.
In the bad old days of pre .NET CF 2.0 we had to write some code like the following:
public MyClassThe above senario is not uncommon for device developers. We are used to writing worker threads to "listen" or just do some work on a separate thread. At some point we need to tell the user that something happend.
{
private delegate void StorageCardRemoved(string message);
private StorageCardRemoved storageCardRemoved = null;
public MyClass()
{
storageCardRemoved =
new StorageCardRemoved(ShowStorageCardRemovedNotification);
}
private void ShowStorageCardRemovedNotification(string name)
{
MessageBox.Show(name);
}
//Event handler from some worker process running somewhere.
private void DeviceManagement_StorageCardRemoved(object sender,
StorageCardChangedEventArgs args)
{
Invoke(storageCardRemoved, args.Name);
}
}
The above code is long and complicated. This is where the Action delegate makes this simple. Consider the above refactored to the following:
public MyClassHow much simpler is that. The only limitation with this is that you can't call anything passing parameters. So you couldn't for example delay the message box processing by calling another delegate as you wouldn't be able to pass it the name (as in this case). This is a limitation within the Invoke method not supporting a paramerterized Action delegate. The action delegate supports upto 4 generic parameters with no returning type. This is the same functionality as per the desktop.
{
//Event handler from some worker process running somewhere.
private void DeviceManagement_StorageCardRemoved(object sender,
StorageCardChangedEventArgs args)
{
Invoke(new Action(() => MessageBox.Show(args.Name)));
}
}
Of course you only need to use Invoke and Action in the above example if the event was received on a thread other than the one that owns the controls underlying window handle (UI thread).
Take another scenario that uses the Action delegate. In this example it is a situation where you have some code to be executed, but each time it is executed you want to do some other stuff first. This initial stuff might need to be specified by the caller at runtime. Consider the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var businessClass =
new BusinessClass(() => Debug.WriteLine("Do initialization stuff"));
businessClass.Process(() => Debug.WriteLine("Now do business process"));
}
}
public class BusinessClassWe have a form with a button event handler hooked up to a button. When we click the button the event handler is called. When we construct the BusinessClass, we pass in the constructor an initialization Action delegate that gets executed when the Process method is called and before the Process Action delegate gets executed.
{
public BusinessClass(Action init)
{
Init = init;
}
public Action Init
{
internal get;
set;
}
public void Process(Action action)
{
Debug.WriteLine("Now entered Process");
Init();
action();
}
}
If we run this code and click the button, the output is as follows:
Now entered ProcessAs you can see, it is quite a powerful and easy implementation. Next I'll talk about the Func delegate....
Do initialization stuff
Now do business process
No comments:
Post a Comment