使用Task.Run的后台线程

jdr*_*oss 5 .net c# multithreading task task-parallel-library

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

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

var partialEmployeeA=ActiveDirectoryLookup(employeeID);

var partialEmployeeB=OracleDBLookup(employeeID);

var finalEmployee=Merge(partialEmployeeA,partialEmployeeB);
Run Code Online (Sandbox Code Playgroud)

此时,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);
Run Code Online (Sandbox Code Playgroud)

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

i3a*_*non 6

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

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

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

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

var partialEmployeeATask = ActiveDirectoryLookupAsync(employeeID);
var partialEmployeeBTask = OracleDBLookupAsync(employeeID);

await Task.WhenAll(partialEmployeeATask, partialEmployeeBTask)
var finalEmployee = Merge(await partialEmployeeATask, await partialEmployeeBTask);
Run Code Online (Sandbox Code Playgroud)

这需要更改API以支持某种形式的异步请求.如果API不在您的控制之下,则可能是一个问题.如果不能这样做至少Task.Run只使用一次并使用"主"线程到另一部分.