Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Run() does not runs asynchronously

I have an ASP.NET MVC 3 site that connects to a WCF service. The WCF Service is independent from the site and is hosted in a Windows Service. Most of the calls are synchronous, so it's not a problem to wait for the WCF to do it's thing.

However, one of those (already implemented) calls takes a bit too long, and, as it essentially does not output anything directly, I wanted to spin it on the service and forget about it.

So I changed my code from:

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  WcfServiceProxy.DoSlowCalculation(calculationOptions);
  ViewBag.Started = true;
  return View();
}

to

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  Task.Run(() =>
  {
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

  ViewBag.Started = true;
  return View();
}

which, as I understand should start an asynchronous request, and return immediately. Still, the execution is completely synchronous, and the UI is frozen until the operation concludes.

What obvious thing am I missing?


Update:

Also, note that I would prefer not to change the server implementation to an async one, just to de-synchronize the call to the service on the call-site.

Moreover, I've noticed that the StartSlowCalculation method finishes executing, but the server does not return a response until the service method finishes executing.

The WCF Service Proxy just does:

public void DoSlowCalculation(CalculationOptions calculationOptions)
{
   //some logging code
   Channel.DoSlowCalculation(calculationOptions);
}

so it's completely synchronous, however that shouldn't matter as it should be executed on an independent thread.

like image 756
SWeko Avatar asked Jul 27 '26 00:07

SWeko


1 Answers

A task operation can run in the calling thread, it depends on taskScheduler decision. To help TaskScheduler make a right decision regarding long running call you can specify task creation option TaskCreationOptions.LongRunning.

And you can check whether task operation is running in a separate thread:

int launchedByThreadId = Thread.CurrentThread.ManagedThreadId;
int launchedInThreadId = -1;
Task.Run(() =>
  {
    launchedInThreadId = Thread.CurrentThread.ManagedThreadId;
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

// then compare whether thread ids are different

BTW, are you using any kind of Task.Wait() operation? It will block calling thread as well.

EDIT:

You might find following post interesting Is Task.Factory.StartNew() guaranteed to use another thread than the calling thread?

So try out using Task.Factory.StartNew() and specify cancellation token even you do not need it, sounds weird but it seems this guarantees that task will not be run eventually in the calling thread. Correct me If I wrong.

like image 167
sll Avatar answered Jul 28 '26 14:07

sll



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!