Reputation: 767
I have a series of methods (with variable number of parameters) that return a Task I want to create a method that does something before and after each of this methods, by passing the Task. I've simplified everything (removed cancellationToken, actual processing, etc) in this sample:
public async Task<string> GetDataString()
{
Console.WriteLine("Executing");
return "test";
}
public async Task<T> Process<T>(Task<T> task)
{
Console.WriteLine("Before");
var res = await task;
Console.WriteLine("After");
return res;
}
And in my main:
Task<string> task = GetDataString();
string result = await Process<string>(tasks);
Console.WriteLine(res);
the console output is
Executing
Before
After
test
What can I do to create the task but not actually starting it? And starting it only before the wait?
I managed to do it by creating a PauseToken, as explained in this article: https://devblogs.microsoft.com/pfxteam/cooperatively-pausing-async-methods/ but I wonder if is there a better way.
Thanks, Mattia
Upvotes: 5
Views: 844
Reputation: 87
You can remove the async keyword (from GetDataString) and create a new task which will be executed when you await
so the result of the code below is : before , executing , test , after
private static async Task Start()
{
Task<string> task = GetDataString();
string result = await Process<string>(task);
Console.WriteLine(result);
Console.ReadLine();
}
public Task<string> GetDataString()
{
return new TaskFactory(TaskScheduler.Default).StartNew(() =>
{
Console.WriteLine("Executing");
return "test";
});
}
public async Task<T> Process<T>(Task<T> task)
{
Console.WriteLine("Before");
var res = await task;
Console.WriteLine("After");
return res;
}
Upvotes: -1
Reputation: 43495
Your generic ProcessAsync
method could accept a task factory as argument:
public async Task<T> ProcessAsync<T>(Func<Task<T>> taskFactory)
{
Console.WriteLine("Before");
var res = await taskFactory();
Console.WriteLine("After");
return res;
}
This way the task will be created at the time you'll invoke the factory method. You are in control of its creation.
Here is an example of calling the ProcessAsync
method, passing as factory a lambda:
var result = await ProcessAsync(() => GetDataStringAsync(arg1, arg2));
This way you are not restricted to a factory method without arguments.
For completeness I should mention that Task
objects can also created in a cold state using the constructor new Task()
, and started later using the Start
method, but this approach is not recommended.
Upvotes: 8