Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Action from Task in C#

Having instantiated one or more Task objects in C#, like this for example:

var tasks = new List<Task>
{
    Task.Factory.StartNew(MyWorker.DoWork),
    Task.Factory.StartNew(AnotherWorker.DoOtherWork)
};

Is there a way to get the Action method from the task object? In other words, can I return the Action of MyWorker.DoWork from its task?

I'm trying to be able to log the status of each task, like this:

Task.WaitAll(tasks.ToArray(), new TimeSpan(0, 0, 1));

var msg = tasks.Aggregate(string.Empty,
    (current, task) =>
        current + $"{task.Action}: {task.Status}{Environment.NewLine}");

The string value of msg would be:

MyWorker.DoWork RanToCompletion
AnotherWorker.DoOtherWork Running

(The {task.Action} portion of my sample doesn't exist and wouldn't compile, of course)

like image 217
Chris Schiffhauer Avatar asked Aug 20 '15 21:08

Chris Schiffhauer


People also ask

How do you return a value from a Task?

You want to return a task result to the client. Set the task's Result property with your user defined result object. The task's Result property is serialized and returned back to the client.

What should I return from Task C#?

The recommended return type of an asynchronous method in C# is Task. You should return Task<T> if you would like to write an asynchronous method that returns a value. If you would like to write an event handler, you can return void instead. Until C# 7.0 an asynchronous method could return Task, Task<T>, or void.

Can an action be async?

For example, action=getstatus is a synchronous action. Actions that can take a significant time to complete are usually asynchronous. These actions are asynchronous because otherwise requests might time out before Media Server is able to process them.

How do I run a 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();


1 Answers

The delegate is stored in the m_action data member on the Task class. You can see that in the reference source.

However, that data member is internal and there's no public way to get to it. You can however use reflection to pick into the insides of a task and look at the contents of m_action.

For example this:

var fooTask = new Task(Foo);
var fieldInfo = typeof(Task).GetField("m_action", BindingFlags.NonPublic | BindingFlags.Instance);
var value = fieldInfo.GetValue(fooTask);
Console.WriteLine(((Action)value).Method);

Outputs (in my specific example):

Void Foo()

A better design option would be to just start all your tasks from a single place in your code that registers all the information you would need outside of the Task itself and use that to log the status.

like image 175
i3arnon Avatar answered Sep 28 '22 01:09

i3arnon