Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreadAbortException when calling Task.Result

I have the following code where I'm trying to make a request to a remote endpoint using HttpClient:

using (var client = new HttpClient())
{
   client.BaseAddress = _serviceBaseAddress;

   Task<HttpResponseMessage> readResponseTask = client.GetAsync(relativeUri);
   readResponseTask.Wait();

   using (var response = readResponseTask.Result)
   {
     if (response.StatusCode == HttpStatusCode.NotFound || !response.IsSuccessStatusCode)
     {
       return default(TResult);
     }

     Task<TResult> readContentTask = response.Content.ReadAsAsync<TResult>();
     readContentTask.Wait();

     TResult value = readContentTask.Result;

     return value;
   }
 }

..and occassionally I would get ThreadAbortException at the readResponseTask.Result like so:

System.Threading.ThreadAbortException: Thread was being aborted. at System.Threading.Monitor.ObjWait(Boolean exitContext, Int32 millisecondsTimeout, Object obj) at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.SpinThenBlockingWait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.InternalWait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)

Under what circumstance will the .Result throw such an exception? I have tried simulating a timeout on the remote endpoint but I got the exception at the .Wait() instead of .Result. Since the exception happens after .Wait(), I'm assuming the result has already been returned from the remote site but somehow something went wrong when it tries to access the result.

Any clues? Could it be something to do with thread concurrency?

like image 783
user1928346 Avatar asked Nov 13 '15 07:11

user1928346


1 Answers

I would get ThreadAbortException at the readResponseTask.Result

No, you don't. The call stack clearly shows that it is in fact the Wait() call that produced the exception. Note the frequent appearance of the word "wait" in the trace.

Hard to see how you got confused. Keep in mind that the Task.Result property getter is very small and is going to be inlined when you run the Release build of your program. So you never can see it back in the stack trace.

Perhaps you'll be ahead by simply removing the Wait() call. It isn't necessary, the Result property getter already performs a wait if necessary.

like image 95
Hans Passant Avatar answered Sep 29 '22 08:09

Hans Passant