后台线程使用 Task.Run
background thread using Task.Run
在为 Oracle 数据库查询和 Active Directory 查询生成两个单独的任务然后等待两者时,您是否看到任何陷阱或问题。
下面是一个非常基本的精简示例。本质上,我们有一个员工对象,它是根据来自 AD 和 Oracle 数据库的信息片段创建的。 (依次调用)
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);
我用秒表 class 做了一些测试,Task
版本每次都恢复得更快(平均:100-120 毫秒对 200-250 毫秒)并且没有问题,但不是确定这是如何在多核系统上扩展的。我对 TPL 的了解不多,但对这种方法很好奇。
我没有发现任何问题,这些是具有不同请求的不同服务,可能不共享任何状态。
但是,您应该意识到,在这两种情况下,您都占用了 3 个线程,这些线程在整个异步 (I/O) 操作中被 阻塞 .
利用多线程并行执行这些操作会更快。但是 它实际上不会更具可扩展性。
要在不阻塞线程和耗尽资源的情况下做到这一点"right",您需要将这些操作视为真正的异步操作,而不仅仅是在后台线程上:
var partialEmployeeATask = ActiveDirectoryLookupAsync(employeeID);
var partialEmployeeBTask = OracleDBLookupAsync(employeeID);
await Task.WhenAll(partialEmployeeATask, partialEmployeeBTask)
var finalEmployee = Merge(await partialEmployeeATask, await partialEmployeeBTask);
这需要更改 API 以支持某种形式的异步请求。如果 API 不受您的控制,那可能是个问题。如果做不到,至少只使用一次 Task.Run
并使用 "main" 线程到另一部分。
在为 Oracle 数据库查询和 Active Directory 查询生成两个单独的任务然后等待两者时,您是否看到任何陷阱或问题。
下面是一个非常基本的精简示例。本质上,我们有一个员工对象,它是根据来自 AD 和 Oracle 数据库的信息片段创建的。 (依次调用)
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);
我用秒表 class 做了一些测试,Task
版本每次都恢复得更快(平均:100-120 毫秒对 200-250 毫秒)并且没有问题,但不是确定这是如何在多核系统上扩展的。我对 TPL 的了解不多,但对这种方法很好奇。
我没有发现任何问题,这些是具有不同请求的不同服务,可能不共享任何状态。
但是,您应该意识到,在这两种情况下,您都占用了 3 个线程,这些线程在整个异步 (I/O) 操作中被 阻塞 .
利用多线程并行执行这些操作会更快。但是 它实际上不会更具可扩展性。
要在不阻塞线程和耗尽资源的情况下做到这一点"right",您需要将这些操作视为真正的异步操作,而不仅仅是在后台线程上:
var partialEmployeeATask = ActiveDirectoryLookupAsync(employeeID);
var partialEmployeeBTask = OracleDBLookupAsync(employeeID);
await Task.WhenAll(partialEmployeeATask, partialEmployeeBTask)
var finalEmployee = Merge(await partialEmployeeATask, await partialEmployeeBTask);
这需要更改 API 以支持某种形式的异步请求。如果 API 不受您的控制,那可能是个问题。如果做不到,至少只使用一次 Task.Run
并使用 "main" 线程到另一部分。