Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task Scheduler with WCF Service Reference async function

I am trying to consume a service reference, making multiple requests at the same time using a task scheduler. The service includes an synchronous and an asynchronous function that returns a result set. I am a bit confused, and I have a couple of initial questions, and then I will share how far I got in each. I am using some logging, concurrency visualizer, and fiddler to investigate. Ultimately I want to use a reactive scheduler to make as many requests as possible.

1) Should I use the async function to make all the requests?

2) If I were to use the synchronous function in multiple tasks what would be the limited resources that would potentially starve my thread count?

Here is what I have so far:

var myScheduler = new myScheduler();
var myFactory = new Factory(myScheduler); 
var myClientProxy = new ClientProxy(); 
var tasks = new List<Task<Response>>();
foreach( var request in Requests )
{
    var localrequest = request;
    tasks.Add( myFactory.StartNew( () =>
        {
            // log stuff
            return  client.GetResponsesAsync( localTransaction.Request );
            // log some more stuff
        }).Unwrap() );
}

Task.WaitAll( tasks.ToArray() );
// process all the requests after they are done

This runs but according to fiddler it just tries to do all of the requests at once. It could be the scheduler but I trust that more then I do the above.

I have also tried to implement it without the unwrap command and instead using an async await delegate and it does the same thing. I have also tried referencing the .result and that seems to do it sequentially. Using the non synchronous service function call with the scheduler/factory it only gets up to about 20 simultaneous requests at the same time per client.

like image 501
Ashtonian Avatar asked Mar 25 '26 19:03

Ashtonian


1 Answers

  1. Yes. It will allow your application to scale better by using fewer threads to accomplish more.
  2. Threads. When you initiate a synchronous operation that is inherently asynchronous (e.g. I/O) you have a blocked thread waiting for the operation to complete. You could however be using this thread in the meantime to execute CPU bound operations.

The simplest way to limit the amount of concurrent requests is to use a SemaphoreSlim which allows to asynchronously wait to enter it:

async Task ConsumeService()
{
    var client = new ClientProxy();
    var semaphore = new SemaphoreSlim(100);
    var tasks = Requests.Select(async request =>
    {
        await semaphore.WaitAsync();
        try
        {
            return await client.GetResponsesAsync(request);
        }
        finally
        {
            semaphore.Release();
        }
    }).ToList();
    await Task.WhenAll(tasks);

    // TODO: Process responses...
}
like image 193
i3arnon Avatar answered Mar 27 '26 08:03

i3arnon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!