HttpClient.(...) GetAsync asla kullanma/zaman uyumsuz bekliyor ne zaman döner
Düzenleme:This question aynı sorun olabilir gibi görünüyor, ama hiç bir yanıt vardır
Düzenleme:Test çalışması 5 görev WaitingForActivation durumda kalmış gibi görünüyor.
Bazı garip davranış Sistemini kullanarak karşılaştım.Net.Http.İçinde HttpClient .NET "" bir çağrı (örneğin) httpClient.GetAsync(...) asla geri gelmeyecek. sonuç bekleyen nerede 4.5 -
Bu sadece yeni zaman uyumsuz/kullanarak dil işlevselliği ve Görevler bekliyor, bazı durumlarda API oluşur - kodu her zaman tek devamı kullanırken iş gibi görünüyor.
Burada sorun üretir bazı kod - yeni içine bu damla "MVC 4 WebApi projesi" Görsel olarak aşağıdaki duyurmak için Studio 11 bitiş:
/api/test1
/api/test2
/api/test3
/api/test4
/api/test5 <--- never completes
/api/test6
Uç noktaları burada her hiç tamamlar aynı verileri (yanıtı stackoverflow.com gelen başlıklar) /api/test5 dışında dönün.
HttpClient sınıfı bir hata karşılaşmış, ya da bir şekilde API kötüye mıyım?
Kod yeniden oluşturmak için:
public class BaseApiController : ApiController
{
/// <summary>
/// Retrieves data using continuations
/// </summary>
protected Task<string> Continuations_GetSomeDataAsync()
{
var httpClient = new HttpClient();
var t = httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead);
return t.ContinueWith(t1 => t1.Result.Content.Headers.ToString());
}
/// <summary>
/// Retrieves data using async/await
/// </summary>
protected async Task<string> AsyncAwait_GetSomeDataAsync()
{
var httpClient = new HttpClient();
var result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead);
return result.Content.Headers.ToString();
}
}
public class Test1Controller : BaseApiController
{
/// <summary>
/// Handles task using Async/Await
/// </summary>
public async Task<string> Get()
{
var data = await Continuations_GetSomeDataAsync();
return data;
}
}
public class Test2Controller : BaseApiController
{
/// <summary>
/// Handles task by blocking the thread until the task completes
/// </summary>
public string Get()
{
var task = Continuations_GetSomeDataAsync();
var data = task.GetAwaiter().GetResult();
return data;
}
}
public class Test3Controller : BaseApiController
{
/// <summary>
/// Passes the task back to the controller host
/// </summary>
public Task<string> Get()
{
return Continuations_GetSomeDataAsync();
}
}
public class Test4Controller : BaseApiController
{
/// <summary>
/// Handles task using Async/Await
/// </summary>
public async Task<string> Get()
{
var data = await AsyncAwait_GetSomeDataAsync();
return data;
}
}
public class Test5Controller : BaseApiController
{
/// <summary>
/// Handles task by blocking the thread until the task completes
/// </summary>
public string Get()
{
var task = AsyncAwait_GetSomeDataAsync();
var data = task.GetAwaiter().GetResult();
return data;
}
}
public class Test6Controller : BaseApiController
{
/// <summary>
/// Passes the task back to the controller host
/// </summary>
public Task<string> Get()
{
return AsyncAwait_GetSomeDataAsync();
}
}
CEVAP
API yanlış kullanıyorsun.
Durum şöyle: ASP.NET sadece bir konuyu bir anda bir isteği işleyebilir. Gerekirse bazı paralel işlem yapabilirsiniz (iş parçacığı havuzu iş parçacığı ek borçlanma), ancak yalnızca bir iş parçacığı istek İçeriği (Ek iş parçacığı isteği olmayan içerik) olurdu.
Bu managed by the ASP.NET SynchronizationContext.
8 ** varsayılan olarak, bir Task yöntem bir özgeçmiş SynchronizationContext (ya da SynchronizationContext yok TaskScheduler, Bir esir) yakaladı. Normalde, bu sizin istediğiniz şey: zaman uyumsuz bir denetleyici eylem 13* *bir şey olacak, ve devam ettiğinde, isteği ile kapsamında kaldığı yerden devam eder.
Yani, burada test5 neden başarısız oldu:
Test5Controller.GetAsyncAwait_GetSomeDataAsync(ASP.NET istek dahilinde) yürütür.AsyncAwait_GetSomeDataAsyncHttpClient.GetAsync(ASP.NET istek dahilinde) yürütür.- HTTP isteği gönderilir ve
HttpClient.GetAsyncTasktamamlanmamış verir. AsyncAwait_GetSomeDataAsynctam olmadığındanTask;,AsyncAwait_GetSomeDataAsyncdönerTasktamamlanmamış bekliyor.Test5Controller.GetengellerTasko kadar geçerli iş parçacığı tamamlar.- HTTP yanıtı gelir ve
TaskHttpClient.GetAsynctarafından döndürülen tamamlandı. AsyncAwait_GetSomeDataAsyncASP.NET istek dahilinde devam ettirmek için çalışır. Ancak, bu bağlamda bir konu var: iplikTest5Controller.Getbloke.- Kilitlenme.
DiÄŸerleri Peki:
- (
test1,test2,test3):Continuations_GetSomeDataAsyncprogramları iş parçacığı havuzu için devamıdışarıdabu ASP.NET bağlam isteği. BuTaskContinuations_GetSomeDataAsynctarafından döndürülen yeniden girmek zorunda kalmadan istek içeriği tamamlamak için izin verir. - (
test4test6):TaskBeribekliyordu, ASP.NET istek iş parçacığı bloke olmaması. BuAsyncAwait_GetSomeDataAsyncdevam etmek için hazır olduğunda ASP.NET istek içeriği kullanmak için izin verir.
Ve burada en iyi uygulamalar:
- "Kütüphane yöntemleri"
asyncmümkün olduğundaConfigureAwait(false)kullanın. Senin durumunda, buAsyncAwait_GetSomeDataAsyncvar result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);olarak değiştirin Tasks blok yok;asynctüm yol aşağı. Diğer bir deyişle,GetResultyerineawait(Task.ResultTask.Waitawaitile değiştirilmelidir) kullanın.
Bu şekilde, hem faydaları: devamı (geri kalan AsyncAwait_GetSomeDataAsync yöntem) bir temel parçacığı havuzu iş parçacığı yok girmek için ASP.NET istek içeriği; ve denetleyici kendisi async (hangi değil blok isteği iş parçacığı).
Daha fazla bilgi için:
- Benim
Taskawaiters nasıl kısa bir açıklama içerirasync/awaitintro post,SynchronizationContext. - Bu kavramlarla ilgili daha fazla ayrıntı gider, 62**,. Ayrıca bakınız Await, and UI, and deadlocks! Oh, my!yokASP.NET
SynchronizationContextsadece bir iş parçacığı bağlama isteği bir anda sınırlar için bir kullanıcı arayüzü yerine, ASP.NET içinde olsan da burada geçerli. - Bu 64**.
- Stephen* *65 so does Lucian Wischik Toub.
Güncelleme 2012-07-13:Dahil bu cevap into a blog post.

Current zaman uyumsuz / çalışmak için ...
Doğru Görev kullanın.Sadece uyumsuz-be...
Kullanarak zaman uyumsuz/çoklu görevle...
Kullanarak zaman uyumsuz bekliyor .net...
zaman uyumsuz/Görev vs bir boşluk dönm...