Background thread using Task.Run

You see any pitfalls or problems when creating two separate tasks for querying Oracle db and querying Active Directory, and then waiting for both.

Below is a very simple example. Essentially, we have an employee object that is created from pieces of information from AD and from an Oracle database. (called sequentially)

var partialEmployeeA=ActiveDirectoryLookup(employeeID); var partialEmployeeB=OracleDBLookup(employeeID); var finalEmployee=Merge(partialEmployeeA,partialEmployeeB); 

At this point, the Employee object was created and assembled along with both requests and can be used. This worked without problems, but if each of these challenges were its own task, would you see any problems in terms of scaling? (excluding any other obvious code issues)

 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); 

I did some testing with the stopwatch class, and the version of Task returned faster every time (avg: 100-120ms vs 200-250 ms) and had no problems, but was not sure how it scales in a multi-core system, I did not do much with TPL but I was curious about this approach.

+5
source share
1 answer

I do not see any problems with this, these are different services with different requests, which probably do not have a common state.

However, you should understand that in both cases you occupy 3 threads that are blocked during the entire asynchronous I / O operation .

It would be faster to perform these operations in parallel using multiple threads. But in reality it will not be more scalable .

To make this β€œcorrect” without blocking the stream and using resources, you need to consider these operations as truly asynchronous, and not just in the background stream:

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

This requires an API change to support asynchronous requests in one form or another. If the API is not under your control, this could be a problem. If this is not possible, at least use Task.Run only once and use the "main" thread for the other part.

+6
source

All Articles