TaskCompletionSource object becomes null in async method when code is compiled in release mode

  • Thread starter Thread starter Premjeet Singh
  • Start date Start date
P

Premjeet Singh

Guest
Hello,

I am using .Net version 4.6.1 and facing a weird issue as a piece of code is working fine when compiled in Debug mode, however, it fails with NullReferenceException when compiled in Release mode.

I have an async method which uses TaskCompletionSource to wait for task completion and I am again retrying after 20 seconds if response is not received. I have reproduced this error in the simplified sample code given below.


internal static readonly ConcurrentDictionary<Guid, TaskCompletionSource<object>> ClientResponses = new ConcurrentDictionary<Guid, TaskCompletionSource<object>>();

public async static Task<object> sendRequest(IHubContext hubContext, ExecuteCommandRequest req)
{
var tcs = new TaskCompletionSource<object>();
ClientResponses.TryAdd(req.requestId, tcs);

try
{
DateTime startTime = DateTime.Now;
while (true)
{
//Call method to send request, It doesn't block the thread
SendRequestForProcessing();
if (tcs == null)
{
System.IO.File.AppendAllText(@"E:\TestError.txt", "tcs is null" + Environment.NewLine);
}

var task = tcs.Task;

//Wait for the client to respond
if (await Task.WhenAny(task, Task.Delay(secondsToWaitBeforeRetryingRequest)) == task)
{
return await task;
}
else
{
if ((DateTime.Now - startTime).TotalSeconds > secondsToWaitForResponse.TotalSeconds)
{
throw new TimeoutException("Could not detect response within " + secondsToWaitForResponse.TotalSeconds.ToString() + " secs.");
}
else
{
//Let's try again
}
}
}
}
finally
{
// Remove the tcs from the dictionary so that we don't leak memory
ClientResponses.TryRemove(req.requestId, out tcs);
}
}


In the above code sample, I have written a log file to write a message if variable 'tcs' becomes null. I get the message when the code is compiled in Release mode; nonetheless, it works fine in Debug mode.

Furthermore, To fix this issue, I have simply moved the below line of code outside the try block and everything is working fine.

var task = tcs.Task;


It appears some kind of .Net bug to me.

Can anyone please help me to understand this awkward behavior?




Regards, Premjeet Singh

Continue reading...
 
Back
Top