locked
Concurrently running multiple taks C# RRS feed

  • Question

  • User-1119641991 posted

    I have REST web API service in IIS which takes a collection of request objects. The user can enter more than 100 request objects.

    I want to run this 100 request concurrently and then aggregate the result and send it back. This involves both I/O operation (calling to backend services for each request) and CPU bound operations (to compute few response elements)

    Code snippet -

    using System.Threading.Tasks;
    ....

    var taskArray = new Task<FlightInformation>[multiFlightStatusRequest.FlightRequests.Count];

    for (int i = 0; i < multiFlightStatusRequest.FlightRequests.Count; i++)
    {
    var z = i;
    taskArray[z] = Tasks.Task.Run(() =>
    PerformLogic(multiFlightStatusRequest.FlightRequests[z],lite, fetchRouteByAnyLeg)
    );
    }
    Task.WaitAll(taskArray);
    for (int i = 0; i < taskArray.Length; i++)
    {
    flightInformations.Add(taskArray[i].Result);
    }

    public Object PerformLogic(Request,...)
    {
    //multiple IO operations each depends on the outcome of the previous result
    //Computations after getting the result from all I/O operations
    }

    If i individually run the PerformLogic operation (for 1 object) it is taking 300 ms, now my requirement is when I run this PerformLogic() for 100 objects in a single request it should take around 2 secs.

    <g class="gr_ gr_14 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="14" data-gr-id="14">PerformLogic</g>() has the following steps - 1. Call a 3rd Party web service to get some details 2. Based on the details call another 3rd Party <g class="gr_ gr_15 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="15" data-gr-id="15">webservice</g> 3. Collect the result from the <g class="gr_ gr_16 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="16" data-gr-id="16">webservice</g>, apply few <g class="gr_ gr_21 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Grammar multiReplace" id="21" data-gr-id="21">transformation</g>. I cannot change this method as this  is used by other applications

    But with Task.run() it takes around 7 secs, I would like to know the best approach to handle concurrency and achieve the desired <g class="gr_ gr_17 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="17" data-gr-id="17">NFR</g> of 2 secs.
    I can see that at any point <g class="gr_ gr_18 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar multiReplace" id="18" data-gr-id="18">of</g> time 7-8 threads are working concurrently

    not sure if I can spawn 100 threads or tasks may be we can see some better performance. Please suggest an approach to handle this efficiently.

    Wednesday, May 16, 2018 9:36 AM

All replies

  • User475983607 posted

    This is a common mistake.  The Tasks.Task.Run() method creates blocking tasks.  Use the async/await pattern. 

    https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh191443(v=vs.110)

    Wednesday, May 16, 2018 10:19 AM
  • User-1119641991 posted

    thanks but I cannot do await inside a for loop, that again defeats the purpose of await/async. Please suggest

    Wednesday, May 16, 2018 11:54 AM
  • User475983607 posted

    thanks but I cannot do await inside a for loop, that again defeats the purpose of await/async. Please suggest

    Not clear. 

    Again, task.run() creates blocking threads.  Rethink the design and use async/await.  The linked document in my previous thread has a lot of information, including many kinked tutorials one of which explains how to handle a list of tasks.  Please read the docs.

    https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh696703%28v%3dvs.110%29

    Wednesday, May 16, 2018 1:01 PM
  • User36583972 posted

    Hi samrecd,

    But with Task.run() it takes around 7 secs, I would like to know the best approach to handle concurrency and achieve the desired NFR of 2 secs.
    I can see that at any point of time 7-8 threads are working concurrently

    not sure if I can spawn 100 threads or tasks may be we can see some better performance. Please suggest an approach to handle this efficiently.

    You cam try implement batch in Web API. The default Web API batch implementation is based on the mime/multipart content type. It accepts mime/multipart requests containing multiple HTTP Requests and processes all the requests sending a mime/multipart response containing the individual responses.

    For more detailed, please see: Introducing batch support in Web API and Web API OData

    Best Regards,

    Yong Lu

    Thursday, May 17, 2018 6:45 AM