Stimmen Sie mit @Darrel Millers Antwort überein. Dies ist ein Fehler. Fügen Sie einfach mehr Details für den Fehlerbericht hinzu.
Das Problem ist, dass intern eine TaskCompletionSource
verwendet wird, aber wenn eine Ausnahme wegen der Stornierung in diesem speziellen Fall ausgelöst wird, wird es nicht gefangen, und die TaskCompletionSource
wird nie in einen der abgeschlossenen Staaten gesetzt (und damit . warten auf die TaskCompletionSource
‚s Task
nie zurückkehren wird
ILSpy Verwendung bei HttpClientHandler.SendAsync
suchen, können Sie sehen die TaskCompletionSource
:
// System.Net.Http.HttpClientHandler
/// <summary>Creates an instance of <see cref="T:System.Net.Http.HttpResponseMessage" /> based on the information provided in the <see cref="T:System.Net.Http.HttpRequestMessage" /> as an operation that will not block.</summary>
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1" />.The task object representing the asynchronous operation.</returns>
/// <param name="request">The HTTP request message.</param>
/// <param name="cancellationToken">A cancellation token to cancel the operation.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="request" /> was null.</exception>
protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException("request", SR.net_http_handler_norequest);
}
this.CheckDisposed();
if (Logging.On)
{
Logging.Enter(Logging.Http, this, "SendAsync", request);
}
this.SetOperationStarted();
TaskCompletionSource<HttpResponseMessage> taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>();
HttpClientHandler.RequestState requestState = new HttpClientHandler.RequestState();
requestState.tcs = taskCompletionSource;
requestState.cancellationToken = cancellationToken;
requestState.requestMessage = request;
this.lastUsedRequestUri = request.RequestUri;
try
{
HttpWebRequest httpWebRequest = this.CreateAndPrepareWebRequest(request);
requestState.webRequest = httpWebRequest;
cancellationToken.Register(HttpClientHandler.onCancel, httpWebRequest);
if (ExecutionContext.IsFlowSuppressed())
{
IWebProxy webProxy = null;
if (this.useProxy)
{
webProxy = (this.proxy ?? WebRequest.DefaultWebProxy);
}
if (this.UseDefaultCredentials || this.Credentials != null || (webProxy != null && webProxy.Credentials != null))
{
this.SafeCaptureIdenity(requestState);
}
}
Task.Factory.StartNew(this.startRequest, requestState);
}
catch (Exception e)
{
this.HandleAsyncException(requestState, e);
}
if (Logging.On)
{
Logging.Exit(Logging.Http, this, "SendAsync", taskCompletionSource.Task);
}
return taskCompletionSource.Task;
}
Später, durch die Leitung Task.Factory.StartNew(this.startRequest, requestState);
wir auf die folgende erhalten Methode:
// System.Net.Http.HttpClientHandler
private void PrepareAndStartContentUpload(HttpClientHandler.RequestState state)
{
HttpContent requestContent = state.requestMessage.Content;
try
{
if (state.requestMessage.Headers.TransferEncodingChunked == true)
{
state.webRequest.SendChunked = true;
this.StartGettingRequestStream(state);
}
else
{
long? contentLength = requestContent.Headers.ContentLength;
if (contentLength.HasValue)
{
state.webRequest.ContentLength = contentLength.Value;
this.StartGettingRequestStream(state);
}
else
{
if (this.maxRequestContentBufferSize == 0L)
{
throw new HttpRequestException(SR.net_http_handler_nocontentlength);
}
requestContent.LoadIntoBufferAsync(this.maxRequestContentBufferSize).ContinueWithStandard(delegate(Task task)
{
if (task.IsFaulted)
{
this.HandleAsyncException(state, task.Exception.GetBaseException());
return;
}
contentLength = requestContent.Headers.ContentLength;
state.webRequest.ContentLength = contentLength.Value;
this.StartGettingRequestStream(state);
});
}
}
}
catch (Exception e)
{
this.HandleAsyncException(state, e);
}
}
Sie werden bemerken, dass der Delegat in dem Aufruf von ContinueWithStandard
innerhalb der Delegierten keine Ausnahmebehandlung hat, und niemand hält sich an die zurückgegebene Aufgabe (und damit, wenn diese Aufgabe löst eine Ausnahme, es ist ignoriert). Der Aufruf von this.StartGettingRequestStream(state);
ist eine Ausnahme:
System.Net.WebException occurred
HResult=-2146233079
Message=The request was aborted: The request was canceled.
Source=System
StackTrace:
at System.Net.HttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
InnerException:
Hier ist die vollständige Aufrufliste zum Zeitpunkt der Ausnahme:
> System.dll!System.Net.HttpWebRequest.BeginGetRequestStream(System.AsyncCallback callback, object state) Line 1370 C#
System.Net.Http.dll!System.Net.Http.HttpClientHandler.StartGettingRequestStream(System.Net.Http.HttpClientHandler.RequestState state) + 0x82 bytes
System.Net.Http.dll!System.Net.Http.HttpClientHandler.PrepareAndStartContentUpload.AnonymousMethod__0(System.Threading.Tasks.Task task) + 0x92 bytes
mscorlib.dll!System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke() Line 59 + 0xc bytes C#
mscorlib.dll!System.Threading.Tasks.Task.Execute() Line 2459 + 0xb bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) Line 2815 + 0x9 bytes C#
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581 + 0xd bytes C#
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 530 + 0xd bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2785 C#
mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2728 C#
mscorlib.dll!System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(System.Threading.Tasks.Task task, bool taskWasPreviouslyQueued) Line 91 + 0xb bytes C#
mscorlib.dll!System.Threading.Tasks.TaskScheduler.TryRunInline(System.Threading.Tasks.Task task, bool taskWasPreviouslyQueued) Line 221 + 0x12 bytes C#
mscorlib.dll!System.Threading.Tasks.TaskContinuation.InlineIfPossibleOrElseQueue(System.Threading.Tasks.Task task, bool needsProtection) Line 259 + 0xe bytes C#
mscorlib.dll!System.Threading.Tasks.StandardTaskContinuation.Run(System.Threading.Tasks.Task completedTask, bool bCanInlineContinuationTask) Line 334 + 0xc bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ContinueWithCore(System.Threading.Tasks.Task continuationTask, System.Threading.Tasks.TaskScheduler scheduler, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions options) Line 4626 + 0x12 bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskScheduler scheduler, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, ref System.Threading.StackCrawlMark stackMark) Line 3840 C#
mscorlib.dll!System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) Line 3805 + 0x1b bytes C#
System.Net.Http.dll!System.Net.Http.HttpUtilities.ContinueWithStandard(System.Threading.Tasks.Task task, System.Action<System.Threading.Tasks.Task> continuation) + 0x2c bytes
System.Net.Http.dll!System.Net.Http.HttpClientHandler.PrepareAndStartContentUpload(System.Net.Http.HttpClientHandler.RequestState state) + 0x16b bytes
System.Net.Http.dll!System.Net.Http.HttpClientHandler.StartRequest(object obj) + 0x5a bytes
mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke() Line 2835 + 0xd bytes C#
mscorlib.dll!System.Threading.Tasks.Task.Execute() Line 2459 + 0xb bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) Line 2815 + 0x9 bytes C#
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581 + 0xd bytes C#
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 530 + 0xd bytes C#
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2785 C#
mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2728 C#
mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 2664 + 0x7 bytes C#
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Line 829 C#
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1170 + 0x5 bytes C#
[Native to Managed Transition]
Ich glaube, die Absicht ist, es nicht zu ignorieren, und im Fall eines Ausnahme rufen Sie die HandleAsyncException
Methode, die TaskCompletionSource
in einen Endzustand setzt.
Sie können einen Deadlock für das Blockieren des Hauptthreads erhalten, hängt es, wenn Sie dies in einer Konsolenanwendung versuchen, oder wenn Sie 'task warten;' statt 'task.Wait'? –
@ScottChamberla Die gleiche Sache passiert mit "warten Aufgabe" und "task.Wait". –
@nick_w, was ist die Ausführungsumgebung dafür (eine Desktop-UI-Anwendung, ASP.NET, Konsole usw.)? Verwenden Sie auch 'token.Register' irgendwo? – Noseratio