简体   繁体   English

我应该将任务包装在另一个任务中还是应该返回创建的任务?

[英]Should I wrap a task in another task or should I just return the created task?

I'm building a .NET 4.0 application that uses ADO.NET, so I cannot use async/await.我正在构建一个使用 ADO.NET 的 .NET 4.0 应用程序,所以我不能使用 async/await。 I don't want a solution for that, but I do want to know what of the following implementations is best and why.我不想要一个解决方案,但我确实想知道以下哪些实现是最好的以及为什么。 My unit tests pass for all three implementations, but I want to know the difference between these three.我的单元测试通过了所有三个实现,但我想知道这三个之间的区别。

#1 Nesting tasks #1 嵌套任务

In my first implementation I wrap a task in another task.在我的第一个实现中,我将一个任务包装在另一个任务中。 I think spinning up two tasks is bad for performance, but I'm not sure.我认为旋转两个任务对性能不利,但我不确定。

public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken)
{
    return Task.Factory.StartNew(() =>
    {
        var sqlCommand = CheckIfSqlCommand(dbCommand);
        PrepareExecuteReader(dbCommand);

        return Task<IDataReader>
            .Factory
            .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null)
            .Result;
    }, cancellationToken);
}

#2 Using TaskCompletionSource #2 使用 TaskCompletionSource

Then I tried wrapping the result in a TaskCompletionSource so I just have one task.然后我尝试将结果包装在TaskCompletionSource因此我只有一项任务。

public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken)
{
    var taskCompletionSource = new TaskCompletionSource<IDataReader>();
    var sqlCommand = CheckIfSqlCommand(dbCommand);
    PrepareExecuteReader(dbCommand);

    var reader = Task<IDataReader>
        .Factory
        .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null)
        .Result;

    taskCompletionSource.SetResult(reader);

    return taskCompletionSource.Task;
}

#3 returning Task directly #3 直接返回Task

My final solution is to directly return the task I created instead of wrapping it.我的最终解决方案是直接返回我创建的任务而不是包装它。

public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken)
{
    var sqlCommand = CheckIfSqlCommand(dbCommand);
    PrepareExecuteReader(dbCommand);

    return Task<IDataReader>
        .Factory
        .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null);
}

So basically my question is:所以基本上我的问题是:

What option should I use or is there a better way to do this?我应该使用什么选项或者有更好的方法来做到这一点?

Your #3 is the best.你的#3 是最好的。 The first two introduce complication for no reason.前两个无缘无故地引入了复杂性。

1 potentially adds another thread purely to run CheckIfSqlCommand() and PrepareExecuteReader() asynchronously. 1 可能会添加另一个线程,纯粹是为了异步运行CheckIfSqlCommand()PrepareExecuteReader() This may be what you wanted, but they don't sound like commands that are going to take a long time.这可能是您想要的,但它们听起来不像需要很长时间的命令。

2 references .Result of the task, which will block until the task is complete, so defeats the whole purpose of using tasks. 2 引用.Result任务,它会阻塞直到任务完成,因此违背了使用任务的全部目的。

There are two scenes we use asynchronous programming with Tasks , one is massive computing, another is I/O .我们在Tasks使用异步编程有两种场景,一种是海量计算,一种是I/O
In massive computing situation, we always use Task.Run to ask a thread from thread pool to avoid blocking thread.在大规模计算的情况下,我们总是使用Task.Run从线程池中请求一个线程以避免阻塞线程。
In I/O situation, if async api is not provided, we always use TaskCompletionSource or Task.Factory.FromAsync to build an async method.I/O情况下,如果没有提供async api,我们总是使用TaskCompletionSourceTask.Factory.FromAsync来构建一个async方法。 I think mix these two is not a good solution.我认为混合这两个不是一个好的解决方案。
By the way, Task.Run is always been used in client application, server end generally not used Task.Run due to concurrent request.顺便说一句, Task.Run总是在客户端应用程序中使用,由于并发请求,服务器端一般不使用Task.Run
Here is a good post you can refer to:这是一个很好的帖子,您可以参考:
https://docs.microsoft.com/en-us/archive/msdn-magazine/2010/september/async-tasks-simplify-asynchronous-programming-with-tasks https://docs.microsoft.com/en-us/archive/msdn-magazine/2010/september/async-tasks-simplify-asynchronous-programming-with-tasks

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

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