Reputation: 316
I'm having an issue where a task is completing, but not returning back. I have a website and a web service on different servers. The website makes a call to the web service which utilizes a library with function myFunction(). If I make a call to myFunction from a console app on the web service's server, it will return as expected. However, when I make the call from the website to the web service to call myFunction(), it will get to "Step 3", but not "Step 4". I have a simplified version of the calls below.
private string myFunction()
{
string myStr = myDoWork().GetAwaiter().GetResult();
return myStr;
}
private async Task<string> myDoWork()
{
logger.Debug("Step 1");
string answer = await aFunction();
logger.Debug("Step 4");
return answer;
}
public async Task<string> aFunction()
{
logger.Debug("Step 2");
return await bFunction(CancellationToken.None);
}
AsyncLock myLock = new AsyncLock();
public Task<string> bFunction(CancellationToken cToken)
{
return Task.Run(
async () =>
{
using (await myLock(cToken))
{
logger.Debug("Step 3");
result = "Hello";
return result;
}
},
cToken);
}
I'm new to async and await, so any help would be appreciated.
Upvotes: 12
Views: 14351
Reputation: 2721
It's almost certainly a deadlock in myFunction()
. Step 4 is scheduled to execute on the main thread, but it can't because the main thread is blocked waiting on GetResult()
.
It should be something closer to this:
private string myFunction()
{
// This is NOT good style - you should avoid blocking on the result of a task.
string myStr = Task.Run(async () => await myDoWork()).GetAwaiter().GetResult();
return myStr;
}
private async Task<string> myDoWork()
{
logger.Debug("Step 1");
string answer = await aFunction();
logger.Debug("Step 4");
return answer;
}
public Task<string> aFunction()
{
logger.Debug("Step 2");
return bFunction(CancellationToken.None);
}
AsyncLock myLock = new AsyncLock();
public async Task<string> bFunction(CancellationToken cToken)
{
using (await myLock(cToken))
{
logger.Debug("Step 3");
return "Hello";
}
}
In general, Task.Run()
should be called from the highest level possible. Keep things as synchronous as possible and let the caller decide if they want to use a background thread.
Upvotes: 12