私はこれを数日間戦い続けてきましたが、それを把握することはできません。あなたの魔術師の1人が私にそれを説明できることを願っています。HttpClientがSendAsyncのデッドロックを待つ
これは、問題のコードです:
public async static Task<RemoteFileDetails> GetRemoteFileDetailsAsync(string strUrl, double dblTimeoutSeconds = 15.0)
{
try
{
using (var hc = new HttpClient())
{
hc.Timeout = TimeSpan.FromSeconds(dblTimeoutSeconds);
using (var h = new HttpRequestMessage(HttpMethod.Head, strUrl))
{
h.Headers.UserAgent.ParseAdd(UserAgent);
using (var rm = await hc.SendAsync(h))
{
rm.EnsureSuccessStatusCode();
return new RemoteFileDetails()
{
Url = strUrl,
FileName = rm.Content.Headers.ContentDisposition.FileName,
FileSize = rm.Content.Headers.ContentLength.GetValueOrDefault(),
LastModified = rm.Content.Headers.LastModified.GetValueOrDefault().LocalDateTime,
Valid = true
};
}
}
}
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
return new RemoteFileDetails();
}
このすべてがありませんされているURLにHEADリクエストに置き、特定のヘッダーの結果をつかみます。
ここでの問題は、デッドロック(約60秒間ポーズした後、TaskCanceledException
を投げた)の約50%であり、もう50%はすばらしく機能します。今、私は、ネットワークのログを追加し、これがデッドロックに何が起こっているかである:
System.Net Verbose: 0 : [2928] HttpWebRequest#3567399::HttpWebRequest(https://www.example.com/file.txt#-114720138)
System.Net Information: 0 : [2928] Current OS installation type is 'Client'.
System.Net Information: 0 : [2928] RAS supported: True
System.Net Verbose: 0 : [2928] Exiting HttpWebRequest#3567399::HttpWebRequest()
System.Net Verbose: 0 : [2928] HttpWebRequest#3567399::HttpWebRequest(uri: 'https://www.example.com/file.txt', connectionGroupName: '565144')
System.Net Verbose: 0 : [2928] Exiting HttpWebRequest#3567399::HttpWebRequest()
System.Net Verbose: 0 : [5456] HttpWebRequest#3567399::BeginGetResponse()
System.Net Verbose: 0 : [2244] HttpWebRequest#3567399::Abort()
System.Net Error: 0 : [2244] Exception in HttpWebRequest#3567399:: - The request was aborted: The request was canceled..
/////// THIS IS WHERE THE 30-60 SECOND PAUSE HAPPENS ////////
System.Net Error: 0 : [5456] Can't retrieve proxy settings for Uri 'https://www.example.com/file.txt'. Error code: 12180.
System.Net Verbose: 0 : [5456] ServicePoint#39086322::ServicePoint(www.example.com:443)
System.Net Information: 0 : [5456] Associating HttpWebRequest#3567399 with ServicePoint#39086322
System.Net Verbose: 0 : [2244] Exiting HttpWebRequest#3567399::Abort()
System.Net Verbose: 0 : [5456] HttpWebRequest#3567399::EndGetResponse()
System.Net Error: 0 : [5456] Exception in HttpWebRequest#3567399::EndGetResponse - The request was aborted: The request was canceled..
System.Net Verbose: 0 : [5456] Exiting HttpWebRequest#3567399::BeginGetResponse() -> ContextAwareResult#36181605
だから、配置されつつあるHttpClientを()オブジェクトのように見えますか?しかしどうですか?これを確認するために、コードを次のように変更しました:
private static HttpClient _hc;
public async static Task<RemoteFileDetails> GetRemoteFileDetailsAsync(string strUrl, double dblTimeoutSeconds = 15.0)
{
_hc = new HttpClient();
try
{
_hc.Timeout = TimeSpan.FromSeconds(dblTimeoutSeconds);
using (var h = new HttpRequestMessage(HttpMethod.Head, strUrl))
{
h.Headers.UserAgent.ParseAdd(UserAgent);
using (var rm = await _hc.SendAsync(h))
{
rm.EnsureSuccessStatusCode();
return new RemoteFileDetails()
{
Url = strUrl,
FileName = rm.Content.Headers.ContentDisposition.FileName,
FileSize = rm.Content.Headers.ContentLength.GetValueOrDefault(),
LastModified = rm.Content.Headers.LastModified.GetValueOrDefault().LocalDateTime,
Valid = true
};
}
}
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
return new RemoteFileDetails();
}
しかし、まだデッドロックしています。
これはなぜ起こっているのですか?私はasync/awaitが基本的にルーチンを一時停止していると考えていたので、HttpClientは決して処理してはいけません。
ここではボートを完全に逃していますが、それは別のものです。ここで
は、例外のSCREENCAPです:ETA: 私はそれは私がこれを呼び出していますどのように示すことが重要だと仮定します。これはMVVM Lightを使用したWPFアプリケーションです。メインビューモデルでは、私はこれを次のように呼び出しています。
public MainViewModel(IDataService ds)
{
_dataService = ds;
this.Initialize();
}
private async void Initialize()
{
var det = await RemoteFileUtils.GetRemoteFileDetailsAsync("https://example.com/file.txt");
}
'.ConfigureAwait(continueOnCapturedContext:false)'を試したことがありますか?私はあなたがUIスレッドからこの関数を直接呼び出すのだろうかと思います。 – xxbbcc
@xxbbccはい、何も変わりません。昨日試しました。私はそれをどのように呼んでいるかを示すために質問を更新する。 – Andy
@xxbbcc OK、私はそれをどのように呼んでいるかを示すために質問を更新しました。 – Andy