私は、System.Net.HttpClient
を短いタイムアウトで使用しているときに、try-catchブロックでラップされていてもプロセスをクラッシュさせることがあることに気付きました。これを再現するための短いプログラムがあります。HttpClientを短すぎるタイムアウトに設定するプロセス
public static void Main(string[] args)
{
var tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(MakeHttpClientRequest());
}
Task.WaitAll(tasks.ToArray());
}
private async static Task MakeHttpClientRequest()
{
var httpClient = new HttpClient { Timeout = TimeSpan.FromMilliseconds(1) };
var request = "whatever";
try
{
HttpResponseMessage result =
await httpClient.PostAsync("http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=766c0ac7802d55314fa980727f747710",
new StringContent(request));
await result.Content.ReadAsStringAsync();
}
catch (Exception x)
{
Console.WriteLine("Error occurred but it is swallowed: " + x);
}
}
次の例外を除いて、プロセスがクラッシュします。この実行:
Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Net.WebException: The request was canceled
at System.Net.ServicePointManager.FindServicePoint(Uri address, IWebProxy proxy, ProxyChain& chain, HttpAbortDelegate& abortDelegate, Int32& abortState)
at System.Net.HttpWebRequest.FindServicePoint(Boolean forceFind)
at System.Net.HttpWebRequest.get_ServicePoint()
at System.Net.AuthenticationState.PrepareState(HttpWebRequest httpWebRequest)
at System.Net.AuthenticationState.ClearSession(HttpWebRequest httpWebRequest)
at System.Net.HttpWebRequest.ClearAuthenticatedConnectionResources()
at System.Net.HttpWebRequest.Abort(Exception exception, Int32 abortState)
at System.Net.HttpWebRequest.Abort()
at System.Net.Http.HttpClientHandler.OnCancel(Object state)
at System.Threading.CancellationCallbackInfo.ExecutionContextCallback(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.CancellationCallbackInfo.ExecuteCallback()
at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
--- End of inner exception stack trace ---
at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
at System.Threading.CancellationTokenSource.NotifyCancellation(Boolean throwOnFirstException)
at System.Threading.CancellationTokenSource.TimerCallbackLogic(Object obj)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
少しで掘り、HttpClient
は、関連ServicePoint
前に要求を中止する場合、作成するHttpWebRequest
試みを作成しているようですServicePoint
、ServicePointManager.FindServicePoint
経由で、RequestCanceledをスローします。この例外は、要求を取り消そうとしているスレッドでスローされるため、キャッチされず、プロセスは終了します。
は、私は何かが足りないのですか?あなたはこの問題にぶつかりましたか?
これはすばらしいバグです。 a)メイン全体でtry-catchを追加できますか? b)TaskScheduler.UnobservedTaskExceptionイベントイベントをフックできますか? – usr
@usr:両方とも試してみましたが、期待通りに役に立たなかった。メインのtry-catchはメインスレッドのものだけをキャッチし、プロセスクラッシュの例外はUnobservedTaskExceptionではありません。 –
aggregateExceptionをキャッチできませんか?そこからそれを扱う? キャッチ(AggregateExceptionのAE) {} – PaulG