简体   繁体   中英

Continuation with Tasks (instead of delegates)

I have a class where each method execute asynchronously, ie return a Task, but where each method should nevertheless wait for the completion of the preceding call.

Continuation, right?

Except that a task continuation takes a delegate (Action) in parameter, not another task.

I've tried different things and the best I could do to make it work is the following (to me quite complex) code:

    private Task QueueTask(Func<Task> futureTask)
    {
        var completionSource = new TaskCompletionSource<int>();

        _lastTask.ContinueWith(async t =>
        {
            try
            {
                await futureTask();

                completionSource.SetResult(0);
            }
            catch (Exception ex)
            {
                completionSource.SetException(ex);
            }
        });

        _lastTask = completionSource.Task;

        return _lastTask;
    }

Here _lastTask is a private member of my class. Since all calls are coming from the UI thread, I just keep the last task and put continuation on it.

As I said I find this code quite convoluted. Do you have a better suggestion?

To me, it seems like you're asking the wrong question. A queue of tasks like this is an unusual requirement. We don't know anything about the actual problem you're trying to solve, so we can't suggest better approaches.

ContinueWith is intended for dynamic parallel processing, so it doesn't quite fit in with async code. However, you can use ContinueWith paired with Unwrap to sort-of emulate the behavior of await (if you ignore how await interacts with the current context).

So you can simplify your queue of tasks solution as such:

private Task QueueTask(Func<Task> futureTask)
{
    _lastTask = _lastTask.ContinueWith(t => futureTask()).Unwrap();
    return _lastTask;
}

However, there are probably better solutions. If the purpose of the queue is to provide exclusive access, a SemaphoreSlim would be more natural. If you actually do need a queue for some reason, consider using a Dataflow mesh.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM