Bu makale makine çevirisi ayna makalesidir, orijinal makaleye geçmek için lütfen buraya tıklayın.

Görünüm: 42759|Yanıt: 5

[Kaynak] .net/c# Görevi neden Thread'den daha yavaş?

[Bağlantıyı kopyala]
Yayınlandı 3.05.2017 16:40:28 | | | |
.NET 4, iş parçacığı işlevselliğini soyutlayan sınıflar içeren yeni bir isim alanı olan System.Threading.Tasks içerir. Arka planda ThreadPool kullanın. Bir görev, tamamlanması gereken bir birimin işini temsil eder. Bu birimin çalışması ayrı bir iş parçacığında çalıştırılabilir veya bir görev senkronize olarak başlatılabilir, bu da ana ayar ipliğini beklemeyi gerektirir. Görevleri kullanmak sadece soyutlama katmanı vermakla kalmaz, aynı zamanda altta yatan iş parçacıkları üzerinde de büyük bir kontrol sağlar.
Görevler, yapılması gereken işleri planlama konusunda büyük esneklik sunar. Örneğin, sürekli bir görev – bir görev tamamlandıktan sonra hangi işin yapılması gerektiği – tanımlayabilirsiniz. Bu, başarılı bir görev ile başarısız iş arasındaki farkı yaratabilir. Ayrıca, görevler hiyerarşi içinde düzenlenebilir. Örneğin, bir ebeveyn görevi yeni bir alt görev oluşturabilir. Bu bir bağımlılık oluşturur; ebeveyn görevi iptal ederseniz, onun alt görevi de iptal edilir.


Günümüzde görev yürütme yöntemleri popüler ve yüksek performanslı, görev performansının nerede olduğunu bilmiyorum.

Task and Thread'i kendim test ettim ve Task'ın çok yavaş olduğunu, bunun performansı büyük ölçüde etkilediğini hissediyorum, test kodu ise şöyle:

Yöntemi 1000 kez döngüye alırız, ardından yöntem 100 milisaniye boyunca bloklanır ve test sonucu şu şekildedir:



Sonuç:
İş parçacığı yürütmesi 188 milisaniye sürer
Görev yürütme süresi 14.671 milisaniye sürüyor


İkisi arasındaki hız farkı 78 kattır!!

Görev çok yavaş, neden böyle olduğunu bilmiyorum, test kodumda bir sorun mu var, yoksa ne? Umarım bunun neden olduğunu açıklayabilirsin...




Önceki:ASP.NET Core ile mesaj gönderin
Önümüzdeki:C# Paralel Hesaplama Paralel.For&Paralel.For
 Ev sahibi| Yayınlandı 13.10.2020 10:47:17 |
tongli1996218 2020-10-13 09:34 tarihinde yayınlandı
Thread ile aynı kodu sağlamak için benim işlemim şu kod ve yukarıdaki sözde koddur
Not: Sadece Task.Delay'i ara, eklemeden ...

Evet, teşekkürler

Görev yürütme süresi: 117.0357

Kodu aşağıdaki gibi değiştirebilirsiniz:

Task.Run, Task.Factory.StartNew'un yerini alır çünkü dahili görevleri otomatik olarak açar.
Task.WaitAll ise dahili bir görev yerine harici bir görev bekler. Task.Run kullanırken iç içe görevler yoktur.


msdn dokümantasyonuna baktığınızda, Task.Delay Method metodunun belirli bir milisaniye sayısı sonra tamamlanan bir görev oluşturduğunu görebilirsiniz. (Aslında, yeni bir iş başlığı oluşturulacak ve görevin yürütülmesini beklemek için wait eklenecek, doğru anladığımı bilmiyorum)

Bağlantı girişi görünür.

Ayrıca, Görev ile boşluk arasında bir fark var

Görev, bekleyebilen asenkron bir yöntem döndürür
Void return asenkron yöntemi bekleyemez, asenkron çalışıyor, ne zaman bittiğini bilemezsiniz, asenkron işlemin durumunu izleyemezsiniz.


Referans:

Bağlantı girişi görünür.
Bağlantı girişi görünür.

Özetle: kodda bir sorun var, Thread.Sleep'i Görev metodu içinde kullanmamalıyım.
Yayınlandı 21.07.2020 13:09:29 |
Bugün aynı sorunu yaşadım, AES şifreleme için çoklu iş parçacığı kullanıyorum, Task Thread'den çok daha yavaş!!
Ev sahibi sebebini buldu mu?
Yayınlandı 12.10.2020 19:24:48 |
Bu gönderi en son tongli1996218 tarafından 2020-10-12 19:43 tarihinde düzenlenmiştir

Sahibin kodunu test ettikten sonra, program birden fazla kez çalıştırıldığında, görevin süresi azalmaya devam ediyor ve bilgisayarımda bu süre Thread'den daha az hale geliyor, ayrıca Thread bu süre içinde stabil oluyor.

Daha sonra Thread.Sleep(100) yönteminin Task'ı olumsuz etkilediği, ancak Thread'i etkilemediği ve Thread.Sleep(100) yönteminin sayısal kendini toplama veya Task.Delay(100) bekleme gibi zaman alıcı program doğrulamalarıyla değiştirilebileceği ortaya çıktı.

Not: Thread.Sleep, çağrıdan sonra mevcut iş parçacığı dilimleme süresini sonlandırır, örneğin Thread.Sleep(0) mevcut iş parçacığı dilimleme süresini sonlandırır ve çalıştırmak için diğer iş parçacıklarına aktarır. Görevin içinde, iş parçacıklarının bağlam değiştirmesini optimize edip CPU kaybı süresini azaltabilen (özellikle çok çekirdekli CPU optimizasyonu için) bir iş parçacığı havuzu bulunurken, Thread.Sleep(100) görevin orijinal iş akışı havuzunun anahtarlama mantığını bozarak çok fazla CPU zaman kaybına yol açar

Thread.Sleep(100) yerine await Task.Delay(100) ile değiştirirseniz, görevin zaman tüketiminin sadece 100 milisaniyeden fazla olduğunu göreceksiniz, aşağıda gösterildiği gibi:
private void TaskTest()
{
        Thread.Sleep(100);
         ... Eylemi gerçekleştir
}
Yerine
private async void TaskTest()
{
      Görevi beklemek. Gecikme(100);
      ... Görev için yürütme süresi 100 milisaniyeden fazla sürer; bu, Thread için orijinal Thread.Sleep(100) ile aynıdır
}




 Ev sahibi| Yayınlandı 12.10.2020 22:53:05 |
tongli1996218 2020-10-12 tarihinde yayınlandı 19:24
Sahibin kodunu test ettikten sonra, program başlatıldığında, görev süresi birden fazla kez çalıştırıldıktan sonra azalmaya devam edecek ve bilgisayarımda Thread'in altında kalacak...

Kod olarak şöyle değiştirdim:
Task.Delay(100000);

Görev yürütme süresi:14.1306 ms, toplam süre gerçekten çok kısa, ancak Görev tarafından çağrılan yöntemin uygulamayı tamamlamadığını gördüm.
Yayınlandı 13.10.2020 09:34:33 |
Bu gönderi en son tongli1996218 tarafından 2020-10-13 09:40 tarihinde düzenlenmiştir
2020-10-12 22:53 tarihinde yayımlandı
Kod olarak şöyle değiştirdim:
Görev.Gecikme(100000);

Thread ile aynı kodu sağlamak için benim işlemim şu kod ve yukarıdaki sözde koddur
Not: Sadece await Task.Delay çağırın ve kod eklemeyin, görev tarafından açılan iş parçacığı hemen döner, böylece hesaplama sınırlı simülasyon sağlanır, (int a = 0; a< 1000000; ++a){}; Bunun yerine böyle yöntemler

private async static void TaskTest()
        {
            beklemek Görev.Gecikme(100000);
             Kilitli.Artış (ref koşusu);    kilitlidir, ama üst gider daha küçüktür
            if(run == j)
             {
                kronometre. Dur(); İzlemeyi durdur
                TimeSpan zaman aralığı = kronometre. Geçmiş;  Mevcut örnekle ölçülen toplam zamanı alır
                Console.WriteLine("Görev yürütme zamanı:" + timespan. TotalMiliseconds); Toplam milisaniye
              }
        Kullanılan süre de çok kısadır


Feragatname:
Code Farmer Network tarafından yayımlanan tüm yazılım, programlama materyalleri veya makaleler yalnızca öğrenme ve araştırma amaçları içindir; Yukarıdaki içerik ticari veya yasa dışı amaçlarla kullanılamaz, aksi takdirde kullanıcılar tüm sonuçları ödemelidir. Bu sitedeki bilgiler internetten alınmakta olup, telif hakkı anlaşmazlıklarının bu siteyle hiçbir ilgisi yoktur. Yukarıdaki içeriği indirmeden sonraki 24 saat içinde bilgisayarınızdan tamamen silmelisiniz. Programı beğendiyseniz, lütfen orijinal yazılımı destekleyin, kayıt satın alın ve daha iyi orijinal hizmetler alın. Herhangi bir ihlal olursa, lütfen bizimle e-posta yoluyla iletişime geçin.

Mail To:help@itsvse.com