Germstorm
Germstorm

Reputation: 9839

Passing method to be executed asynch

I am creating a Windows forms application which executes a lot of similar operations on a piece of data. All these operations are almost the same so I would like to create a single method that

I imagine calling this single method like

ExecuteOperation([method to execute], "Executing operation1")

I am sure that this is simple but I am lost between delegates and tasks so please show me how to write a method that is capable of running a selected method, preferably with multiple parameters and how this method is called.

Note:

By disabling the interface I mean

MainMenu.Enabled = false;
txtData.ReadOnly = true;

Upvotes: 0

Views: 85

Answers (3)

Curtis Rutland
Curtis Rutland

Reputation: 786

You can pass methods into methods, so to speak, but the delegates have to match. If you have methods with different signatures, you're angling the wrong way.

The Action and Func delegates are generic. There's one to match almost any signature (up to 16 parameters), but again, they have to match the method signature. If you have one method with one parameter, and another with two, or two with different types of parameters, you can't pass those into the same delegate.

So, really it depends on how similar your methods are. If they have varied types of parameters, you'd probably have to "wrap" these calls.

Simplified example:

void Main()
{
    List<Action> actions = new List<Action>
    {
        () => Method1("myString"),
        () => Method2("myString2", "myString3")
    };
    foreach(var action in actions) InvokeAction(action);
}

void InvokeAction(Action action)
{
    action();
}

void Method1(string x)
{
    Console.WriteLine(x);
}

void Method2(string y, string z)
{
    Console.WriteLine(y);
    Console.WriteLine(z);
}

On the other hand, if your methods have the same signature, it's a bit simpler:

void Main()
{
    InvokeAction(Method1, "myString");
    InvokeAction(Method2, "myString2");
}

void InvokeAction(Action<string> action, string param)
{
    action(param);
}

void Method1(string x)
{
    Console.WriteLine(x);
}

void Method2(string y)
{
    Console.WriteLine(y);
}

Now, as to running that asynchronously, it's as simple as using a System.Threading.Task, if you're on .NET 4.0. You could alter my example method as such:

void InvokeAction(Action<string> action, string param)
{
    Task.Factory.StartNew(() => action(param));
}

Upvotes: 1

Jay
Jay

Reputation: 10108

How about something like this (non async/await - version):

void Foo<T>(Action<T> action, string message)
{
  MethodWhichMakesMyInterfaceReadOnlyAndSetsMessage(message);
  BackgroundWorker worker = new BackgroundWorker();
  worker.DoWork += (obj, arg) => action.Invoke();
  worker.RunWorkerCompleted += 
       (obj, arg) => 
        {
           MethodWhichMakesMyInterfaceReadWrite();
        };

  worker.RunWorkerAsync();
}

I wrote this before I realised you wanted async/await and tasks specifically - someone else has answered with that however. You can create whatever overloads you want for the extra params for your action.

Upvotes: 0

Dan Bryant
Dan Bryant

Reputation: 27495

You're probably looking for something like this (I've shown an example here for a method that takes parameters, since you asked for that case specifically):

    private async Task ExecuteOperation(string operationName, Action action)
    {
        //Disable UI here
        //Set 'Executing' message here
        await Task.Run(action);
        //Set 'Finished' message here
        //Enable UI here
    }

    private async Task CallOperation()
    {
        int x, y, z; //These get set to something here...
        await ExecuteOperation("Operation1", () => OperationWithParams(x, y, z));
    }

You most likely also want to add some exception handling in your ExecuteOperation wrapper if you have standard exceptions that your various operations can throw and which should result in UI feedback of some sort.

On a side note, I reordered the name and the action, as this makes it somewhat cleaner (IMO) to pass an anonymous method as the action.

Upvotes: 3

Related Questions