简体   繁体   English

继续执行任务(而不是代表)

[英]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. 我有一个类,其中每个方法异步执行,即返回一个Task,但是每个方法仍应等待上一个调用的完成。

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. _lastTask是我班的私人成员。 Since all calls are coming from the UI thread, I just keep the last task and put continuation on it. 由于所有调用都来自UI线程,因此我只保留最后一个任务并继续执行。

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. ContinueWith用于动态并行处理,因此它不太适合async代码。 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). 但是,您可以将ContinueWithUnwrap配对使用,以对await的行为进行排序(如果忽略了await与当前上下文的交互方式)。

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. 如果队列的目的是提供独占访问,则SemaphoreSlim会更自然。 If you actually do need a queue for some reason, consider using a Dataflow mesh. 如果实际上由于某种原因确实需要队列,请考虑使用数据流网格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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