Passing a task as parameter

2019-02-21 16:11发布

问题:

I am not sure whether this is possible, so here me out:

I have a sequence of action to perform multiple

async Task MethodA(...)
{
    // some code
    // a call to specific Async IO bound method
    // some code
}

there are also MethodB(), MethodC(), etc, and all of the have exactly the same code, except for the call to specific Async IO bound method. I am trying to find a way to pass a task pointer to a method, so that we can execute it later in a Method().

What i am currently doing is this:

private async Task Method(Func<Task<Entity>> func)
{
    // some code
    var a = await task.Run(func);
    // some code
}

var task = async () => await CallToIOBoundTask(params);
Method(task);

This code, however, pulls a new thread each time, which is not required for IO bound task, and should be avoided.

So, is there a way to refactor the code so that no ThreadPool thread is used? A goal is to have a code like this:

private async Task Method(Task<Entity> task)
{
    // some code
    var a = await task;
    // some code
}

It is also important to mention that different IO calls have different method signatures. Also, a task can start to execute only in Method() body, and not before.

回答1:

Of course, simply invoke the func, get back a task, and await it:

async Task Method(Func<Task<Entity>> func)
{
    // some code
    var a = await func();
    // some code
}

Also, when you're sending that lambda expression, since all it's doing is calling an async method which in itself returns a task, it doesn't need to be async in itself:

Method(() => CallToIOBoundTask(params));

That's fine as long as all these calls return Task<Entity>. If not, you can only use Task (which means starting the operation and awaiting its completion) and you won't be able to use the result.