HttpClient SendAsync ana iş parçacığını engeller
Yerel ağımdaki her ip adresine, belirli bir aygıtımı keşfetmek için http istekleri gönderen küçük bir winforms uygulaması yazdım. Benim alt ağ maskemde 512 adres var. Bunu backGroundWorker kullanarak yazdım ama aynı şeyi elde etmek için httpClient ve Async / Await modelini denemek istedim. Aşağıdaki kod tek bir httpClient örneğini kullanıyor ve tüm istekler tamamlanana kadar bekliyorum. Bu sorun, ana iş parçacığının engellenmesidir. Bunu biliyorum çünkü bir resim kutusu + yükleme gif'im var ve tekdüze hareket etmiyor. GetAsync yöntemini burada önerildiği gibi bir Task.Run içine koydum ama bu da işe yaramadı.
private async void button1_Click(object sender, EventArgs e)
{
var addresses = networkUtils.generateIPRange..
await MakeMultipleHttpRequests(addresses);
}
public async Task MakeMultipleHttpRequests(IPAddress[] addresses)
{
List<Task<HttpResponseMessage>> httpTasks = new List<Task<HttpResponseMessage>>();
foreach (var address in addresses)
{
Task<HttpResponseMessage> response = MakeHttpGetRequest(address.ToString());
httpTasks.Add(response);
}
try
{
if (httpTasks.ToArray().Length != 0)
{
await Task.WhenAll(httpTasks.ToArray());
}
}
catch (Exception ex)
{
Console.WriteLine("\thttp tasks did not complete Exception : {0}", ex.Message);
}
}
private async Task<HttpResponseMessage> MakeHttpGetRequest(string address)
{
var url = string.Format("http://{0}/getStatus", address);
var cts = new System.Threading.CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(10));
HttpResponseMessage response = null;
var request = new HttpRequestMessage(HttpMethod.Get, url);
response = await httpClient.SendAsync(request, cts.Token);
return response;
}
Burada benzer bir konu okudum ama gui iş parçacığım pek bir şey yapmıyor. Burada okudum , belki ipliklerim bitiyor. Sorun bu mu, nasıl çözebilirim? Bunun Send Async olduğunu biliyorum çünkü kodu aşağıdaki basit görevle değiştirirsem engelleme olmaz.
await Task.Run(() =>
{
Thread.Sleep(1000);
});
Yanıtlar
Dolayısıyla buradaki sorunlardan biri, görev oluşturma dışında bir zaman aşımı ayarıyla arka arkaya 500'den fazla görev oluşturuyor olmanızdır.
500'den fazla görevi çalıştırmayı istemeniz, 500'den fazla görevin aynı anda çalışacağı anlamına gelmez. Planlayıcı mümkün olduğunu düşündüğünde sıraya alınır ve çalıştırılır.
10 saniyelik oluşturma anında bir zaman aşımı ayarlarsınız. Ancak, daha yürütülmeden önce programlayıcıda 10 saniye oturabilirler.
Http isteklerinizin organik olarak zaman aşımına uğramasını istiyorsanız, bunu şu şekilde yapabilirsiniz HttpClient:
private static readonly HttpClient _httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
Yani, zaman aşımını öğesine taşıyarak, HttpClientyönteminiz şimdi şöyle görünmelidir:
private static Task<HttpResponseMessage> MakeHttpGetRequest(string address)
{
return _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, new UriBuilder
{
Host = address,
Path = "getStatus"
}.Uri));
}
Bu yöntemi kullanmayı deneyin ve Hata Ayıklama modunda kilitlenme sorununuzu iyileştirip iyileştirmediğine bakın.
Uzağa sorunu kadar edildi sahip: Eğer hata ayıklama modunda olan ve ayıklayıcı söylemeye çalışıyor çünkü kilitleme oluyor 500 kez tüm "hey, bir istisna var" aynı anda hepsi kökenli çünkü aynı anda . Yayın modunda çalıştırın ve hala kilitlenip kilitlenmediğine bakın.
Yapmayı düşündüğüm şey, operasyonlarınızı gruplamaktır. 20'yi yapın, sonra bu 20'nin bitmesini bekleyin, 20 tane daha yapın, vb.
Görevleri toplu hale getirmenin şık bir yolunu görmek isterseniz, bana bildirin, size göstermekten çok mutlu olurum.
.NET Framework'te, bir sunucuya yapılan bağlantıların sayısı ServicePointManager Sınıfı tarafından kontrol edilir .
Bir istemci için varsayılan bağlantı sınırı olan 2 istemci süreçlerine.
Kaç tane HttpClient.SendAsync çağrısı yaparsanız yapın, aynı anda sadece 2 tanesi aktif olacaktır.
Ancak bağlantıları kendiniz yönetebilirsiniz .
.NET Core'da burada hizmet noktası yöneticisi kavramı değildir ve eşdeğer varsayılan sınır int.MaxValue'dur.