【问题标题】:background thread using Task.Run使用 Task.Run 的后台线程
【发布时间】:2015-08-23 14:13:53
【问题描述】:

在为 Oracle 数据库查询和 Active Directory 查询生成两个单独的任务然后等待两者时,您是否发现任何陷阱或问题。

下面是一个非常基本的精简示例。本质上,我们有一个员工对象,它是从 AD 和 Oracle DB 的信息中创建的。 (顺序调用)

var partialEmployeeA=ActiveDirectoryLookup(employeeID);

var partialEmployeeB=OracleDBLookup(employeeID);

var finalEmployee=Merge(partialEmployeeA,partialEmployeeB);

此时Employee 对象已创建并从两个查询拼凑在一起并且可以使用。这没有问题,但如果这些调用中的每一个都是它自己的任务,你会从扩展的角度看到任何问题吗? (不包括任何其他明显的代码问题)

Employee partialEmployeeA;
Employee partialEmployeeB;

var t1 = Task.Run(() => {
   partialEmployeeA=ActiveDirectoryLookup(employeeID);
});

var t2 = Task.Run(() => {
   partialEmployeeB=OracleDBLookup(employeeID);
});,

Task.WaitAll(t1, t2);
var finalEmployee=Merge(partialEmployeeA,partialEmployeeB);

我对秒表类进行了一些测试,Task 版本每次都恢复得更快(平均:100-120 毫秒 vs 200-250 毫秒)并且没有问题,但不确定在多核系统上如何扩展.我没有对 TPL 做过很多,但对这种方法很好奇。

【问题讨论】:

    标签: c# .net multithreading task-parallel-library task


    【解决方案1】:

    我认为这没有任何问题,这些是具有不同请求的不同服务,可能不共享任何状态。

    但是,您应该意识到,在这两种情况下,您都占用了 3 个线程,这些线程在整个异步 (I/O) 操作中都被阻塞

    利用多个线程并行执行这些操作会更快。但它实际上不会更具可扩展性

    要在不阻塞线程和耗尽资源的情况下“正确”执行此操作,您需要将这些操作视为真正的异步,而不仅仅是在后台线程上:

    var partialEmployeeATask = ActiveDirectoryLookupAsync(employeeID);
    var partialEmployeeBTask = OracleDBLookupAsync(employeeID);
    
    await Task.WhenAll(partialEmployeeATask, partialEmployeeBTask)
    var finalEmployee = Merge(await partialEmployeeATask, await partialEmployeeBTask);
    

    这需要更改 API 以支持某种形式的异步请求。如果 API 不受您的控制,这可能是个问题。如果无法做到这一点,至少只使用一次Task.Run,然后将“主”线程用于另一部分。

    【讨论】:

    • 既然任务已经用await Task.WhenAll 等待,那么在合并过程中使用.Result 而不是再次等待它们不是更好吗?或者更好的是,由于这两个任务都返回结果,你不能从await Task.WhenAll 的结果中获取结果作为数组吗?
    • 非常感谢 i3arnon 的回复。你能解释更多关于被阻塞的线程与并行选项的信息吗?我只是不熟悉会产生的影响或何时避免该路线。
    • @jdross 调用数据库(oracle 或 AD)需要 I/O(即发送网络消息并等待响应)。这需要很长时间。同时,线程无法继续处理(因为它正在等待响应),因此它处于空闲状态等待。这就是我所说的被阻止的意思。
    • @jdross 当操作是异步的时,你释放线程,而 I/O 操作仍然“在飞行中”,这样你就可以处理其他代码了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多