Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a Task with an Action<T>

I somehow feel I am missing something basic. Here's my problem.

I am trying to create a System.Threading.Tasks.Task instance to execute an action that accepts a parameter of a certain type. I thought I could do something like

void DoWork(MyClass obj) {} //My action that accepts a parameter of type 'MyClass'

MyClass obj = new MyClass(); 
Action<MyClass> action = DoWork; //action that points to the method
Task task = new Task(action,obj); //task that would execute 'DoWork' with 'obj' as the parameter when I call Start.

Obviously this does not compile. It seems I can only use an Action<object> and not an Action<T> for a task and then cast the 'object' to T inside my method.

How can I achieve what I want most effectively and efficiently?

like image 520
alwayslearning Avatar asked Oct 24 '12 09:10

alwayslearning


People also ask

What is Task run ()?

The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method. It creates a task with the following default values: Its cancellation token is CancellationToken.

How do I create a new Task in C#?

To start a task in C#, follow any of the below given ways. Use a delegate to start a task. Task t = new Task(delegate { PrintMessage(); }); t. Start();

What are tasks in C#?

A task is an object that represents some work that should be done. The task can tell you if the work is completed and if the operation returns a result, the task gives you the result.

What is Task constructor?

The Task Constructor framework provides a flexible and transparent way to define and plan actions that consist of multiple interdependent subtasks. It draws on the planning capabilities of MoveIt to solve individual subproblems in black-box planning stages.


2 Answers

You also can use directly:

MyClass obj = new MyClass();
Task task = Task.Run(() => DoWork(obj));
like image 113
cuongle Avatar answered Oct 07 '22 23:10

cuongle


You could use

Action<Object> action = o => DoWork((MyClass)o);
Task task = new Task(action, obj);

If you're using .NET 4.0 or above, you can use Contravariance to achieve your goal without introducing a new delegate

//INCORRECT Code, casts InvalidCastException at runtime
Action action = DoWork;
Task task = new Task((Action)action, obj);

EDIT:

Thanks for @svick for pointing out, that the second option is not correct: I was too busy sorting out, whether Action is co- or contravariant (it is in fact contravariant, I was right about this at least) that I oversaw, that I would need Covariance in this case.

Contravariance means that you can do

Action<object> action1 = someAction;
Action<SubClass> action2 = action1;

without explicit casting.

like image 40
MartinStettner Avatar answered Oct 07 '22 21:10

MartinStettner