Sorunuzda birkaç soru sordunuz. Onları senden biraz farklı bir şekilde parçalayacağım. Ama önce soruyu doğrudan cevaplayayım.
Hepimiz hafif, yüksek kaliteli ve ucuz bir kamera istiyoruz, ancak deyişe göre, bu üçten en fazla ikisini alabilirsiniz. Burada aynı durumdasınız. Senkronize ve senkronize olmayan yollar arasında verimli, güvenli ve kodu paylaşan bir çözüm istiyorsunuz. Onlardan sadece ikisini alacaksın.
Bunun nedenini yıkayım. Bu soru ile başlayacağız:
İnsanların GetAwaiter().GetResult()
bir zaman uyumsuz yöntemde kullanabileceğinizi ve bunu senkronizasyon yönteminizden çağırabileceğini söylediğini gördüm. Bu iş parçacığı tüm senaryolarda güvenli midir?
Bu sorunun amacı, "eşzamanlı yolun eşzamansız sürümde eşzamanlı bir bekleme yapmasını sağlayarak eşzamanlı ve eşzamansız yolları paylaşabilir miyim?"
Bu noktada çok net olalım, çünkü önemli:
DERHAL OLARAK BU İNSANLARDAN HERHANGİ BİR TAVSİYE ALMALISINIZ .
Bu son derece kötü bir tavsiye. Görevin normal veya anormal şekilde tamamlandığına dair kanıtınız yoksa , eşzamansız bir görevden bir sonucu senkronize olarak almak çok tehlikelidir .
Bunun son derece kötü bir tavsiye olmasının nedeni, bu senaryoyu düşünmektir. Çim biçmek istiyorsunuz, ancak çim biçme bıçağınız kırıldı. Bu iş akışını izlemeye karar verdiniz:
- Bir web sitesinden yeni bir bıçak sipariş edin. Bu, yüksek gecikmeli, eşzamansız bir işlemdir.
- Eşzamanlı olarak bekleyin - yani bıçağı elinize alana kadar uyuyun .
- Bıçağın gelip gelmediğini görmek için posta kutusunu düzenli olarak kontrol edin.
- Bıçağı kutudan çıkarın. Şimdi elinizde.
- Bıçağı biçiciye takın.
- Çimleri biçmek.
Ne oluyor? Sonsuza kadar uyuyorsunuz çünkü postayı kontrol etme işlemi artık posta geldikten sonra gerçekleşen bir şeye bağlı .
Öyle oldukça kolay zaman uyumlu keyfi bir görev beklemek zaman bu durumlarla karşılaşmak. Bu görevin şimdi bekleyen iş parçacığının geleceğinde planlanmış çalışması olabilir ve şimdi bu gelecek asla beklemediğiniz için gelmeyecektir.
Asenkron bir bekleme yaparsanız, o zaman her şey yolunda! Postayı düzenli aralıklarla kontrol edersiniz ve beklerken bir sandviç yapar veya vergilerinizi veya her neyse yaparsınız; beklerken işlerinizi yapmaya devam edersiniz.
Asla eşzamanlı olarak beklemeyin. Görev tamamlandıysa, gereksizdir . Görev tamamlanmadıysa, ancak geçerli iş parçacığının çalışması planlanıyorsa, geçerli iş parçacığı beklemek yerine başka işlere hizmet ediyor olabileceğinden , verimsizdir . Görev tamamlanmazsa ve geçerli iş parçacığında zamanlama çalıştırılırsa, eşzamanlı olarak beklemeye asılı kalır. Görevin tamamlandığını zaten bilmiyorsanız , eşzamanlı olarak beklemek için iyi bir neden yoktur .
Bu konu hakkında daha fazla bilgi için bkz.
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Stephen gerçek dünya senaryosunu benden çok daha iyi açıklıyor.
Şimdi "diğer yönü" ele alalım. Eşzamansız sürümü basitçe bir işçi iş parçacığındaki eşzamanlı sürümü yaparak kod paylaşabilir miyiz?
Yani muhtemelen ve gerçekten de muhtemelen aşağıdaki nedenlerden dolayı kötü bir fikir.
Senkron işlemin yüksek gecikmeli IO çalışması olması verimsizdir. Bu aslında bir çalışanı işe alır ve bir görev tamamlanana kadar o çalışanı uyutur . İplikler inanılmaz derecede pahalıdır . Varsayılan olarak minimum bir milyon bayt adres alanı tüketirler, zaman alırlar, işletim sistemi kaynaklarını alırlar; işe yaramaz bir iş yaparak bir iplik yakmak istemezsiniz.
Eşzamanlı işlem, iş parçacığı için güvenli olarak yazılmamış olabilir.
Bu , yüksek gecikmeli çalışma işlemciye bağlıysa daha makul bir tekniktir, ancak eğer öyleyse muhtemelen bir iş parçacığına teslim etmek istemezsiniz. Muhtemelen görev paralel kütüphanesini mümkün olduğunca çok CPU'ya paralel hale getirmek için kullanmak istersiniz, muhtemelen iptal mantığı istersiniz ve senkronize versiyonun hepsini yapmasını sağlayamazsınız, çünkü o zaman zaten senkronize olmayan versiyon olacaktır .
Daha fazla okuma; Yine, Stephen bunu çok açık bir şekilde açıklıyor:
Neden Görev'i kullanmıyorsunuz?
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html
Task.Run için daha fazla "yapma ve yapma" senaryosu:
https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html
O zaman bizi ne bırakıyor? Her iki kod paylaşım tekniği ya kilitlenmelere ya da büyük verimsizliklere yol açar. Ulaştığımız sonuç, bir seçim yapmanız gerektiğidir. Verimli ve doğru olan ve arayanı memnun eden bir program mı istiyorsunuz, yoksa eşzamanlı ve eşzamansız yollar arasında az miktarda kod çoğaltarak gerekli birkaç tuş vuruşunu kaydetmek mi istiyorsunuz? İkisini de alamıyorsun, korkuyorum.