C # 5.0'da zaman uyumsuz ve normal işlevler arasındaki satırları bulanıklaştırma


10

Son zamanlarda C # 5.0 şaşırtıcı async-bekliyor desen yeterince alamıyorum görünmüyor . Tüm hayatım boyunca neredeydin?

Basit sözdiziminden kesinlikle heyecan duyuyorum, ancak küçük bir zorluk yaşıyorum. Benim sorunum, asenkron fonksiyonların normal fonksiyonlardan tamamen farklı bir beyanı olmasıdır. Sadece zaman uyumsuz işlevler diğer zaman uyumsuz işlevleri üzerinde bekleyebilir beri, bazı eski engelleme kodunu zaman uyumsuzluğa aktarmaya çalıştığımda, dönüştürmem gereken işlevlerin domino etkisi yaşıyorum.

İnsanlar buna bir zombi istilası olarak atıfta bulunuyorlar . Zaman uyumsuz kodunuzda bir ısırık aldığında, gittikçe büyür. Taşıma işlemi zor değildir, sadece asyncbeyanda bulunmak ve dönüş değerini ile sarmaktır Task<>. Ancak eski senkron kodu taşırken bunu tekrar tekrar yapmak can sıkıcı bir durum.

Bana göre, her iki işlev türünün (async ve normal eski eşitleme) aynı sözdizimine sahip olması çok daha doğal olacaktır. Eğer durum buysa, taşıma işlemi sıfır çaba gerektirecek ve iki form arasında ağrısız bir şekilde geçiş yapabilirdim.

Bu kuralları izlersek bunun işe yarayabileceğini düşünüyorum:

  1. Zaman uyumsuz işlevler asyncartık bildirim gerektirmez . Geri dönüş türlerinin sarılması gerekmez Task<>. Derleyici, derleme sırasında kendiliğinden bir eşzamansızlık işlevi belirler ve gerektiğinde Görev <> sarma işlemini otomatik olarak yapar.

  2. Artık eşzamansız işlevlere ateşle ve unut çağrılarına son. Bir eşzamansız işlevi çağırmak istiyorsanız, onu beklemeniz gerekir. Zaten ateşle ve unut kullanıyorum ve çılgın yarış koşullarının veya kilitlenmelerin tüm örnekleri her zaman bunlara dayanıyor gibi görünüyor. Bence çok kafa karıştırıcılar ve kaldıraçlı zihniyetle “temasta kalmıyorlar”.

  3. Eğer gerçekten ateş et ve unut olmadan yaşayamazsan, bunun için özel bir sözdizimi olacak. Her durumda, bahsettiğim basit birleşik sözdiziminin bir parçası olmayacak.

  4. Eşzamansız bir çağrıyı belirtmek için ihtiyacınız olan tek anahtar kelime await. Bekliyorsanız, çağrı zaman uyumsuzdur. Eğer yapmazsanız, çağrı düz eski eşzamanlıdır (unutmayın, artık ateşle ve unut.

  5. Derleyici async işlevlerini otomatik olarak tanımlayacaktır (artık özel bir bildirimi olmadığından). Kural 4 bunu yapmayı çok kolaylaştırır - bir fonksiyonun içinde bir awaitçağrı varsa , bu zaman uyumsuzdur.

Bu işe yarayabilir mi? yoksa bir şey mi kaçırıyorum? Bu birleşik sözdizimi çok daha akıcıdır ve zombi istilasını tamamen çözebilir.

Bazı örnekler:

// assume this is an async function (has await calls inside)
int CalcRemoteBalanceAsync() { ... }

// assume this is a regular sync function (has no await calls inside)
int CalcRemoteBalance() { ... }

// now let's try all combinations and see what they do:

// this is the common synchronous case - it will block
int b1 = CalcRemoteBalance();

// this is the common asynchronous case - it will not block
int b2 = await CalcRemoteBalanceAsync();

// choosing to call an asynchronous function in a synchronous manner - it will block
// this syntax was used previously for async fire-and-forget, but now it's just synchronous
int b3 = CalcRemoteBalanceAsync();

// strange combination - it will block since it's calling a synchronous function
// it should probably show a compilation warning though
int b4 = await CalcRemoteBalance();

Not: Bu ilginç bir devamıdır ilgili tartışma SO içinde


3
Her zaman asenkron işlemlerinizi mi bekliyorsunuz? Lütfen bunu
kovduktan

1
Ayrıca, zaman uyumsuzluğunun en güzel yanlarından biri, awaithemen yapmak zorunda olmamanızdır . Gibi bir şey yapabilirsiniz var task = FooAsync(); Bar(); await task;. Bunu teklifinizde nasıl yapardım?
svick

3
SO bir tartışma mı yaşıyor? BFG-3000'im nerede ...
Robert Harvey

2
@talkol Paralel programlamanın müstehcen olduğunu mu düşünüyorsunuz? Bu, en azından söylemek gerekirse, ilginç bir bakış açısı async. Bence bu büyük avantajlardan biri async- await: kolayca senkronize olmayan işlemler oluşturmak için izin verir (ve sadece en basit "başlangıç ​​A, A için bekleyin, B başlatmak, B için bekleyin" yolu). Ve zaten tam olarak bu amaç için özel bir sözdizimi var: buna denir await.
svick

1
@svick haha, şimdi oraya gittik :) Ben paralel prog müstehcen olduğunu sanmıyorum, ama bence async-bekliyor bekliyor. Async-await, engelleme bedelini ödemeden senkron durumunuzu korumak için sözdizimsel şekerdir. Zaten paralel düşünüyorsanız, farklı bir desen kullanmanızı tavsiye ederim
talkol

Yanıtlar:


9

Sorunuz, bağladığınız SO sorusunda zaten yanıtlandı.

Asenkron / beklemenin amacı, birçok yüksek gecikme işlemi olan bir dünyada kod yazmayı kolaylaştırmaktır. Operasyonlarınızın büyük çoğunluğu yüksek gecikme değildir .

Ne zaman WinRT ilk çıktığında, tasarımcılar onlar operasyonları zaman uyumsuz olacak edildiği karar nasıl tarif ediyordu. 50ms veya daha fazla sürecek her şeyin zaman uyumsuz olacağına ve yöntemlerin geri kalanının sıradan, eşzamansız olmayan yöntemlere karar verdiler.

Bunları eşzamansız hale getirmek için kaç yöntem yeniden yazılmak zorundaydı? Bunların yaklaşık yüzde 10'u. Diğer% 90'ı hiç etkilenmedi.

Eric Lippert neden tek bedene yakışır bir yaklaşım benimsemeyi seçtiklerini oldukça önemli teknik ayrıntılarıyla açıklıyor. O temelde söylüyor asyncve awaitdevam-geçen tarzda kısmi uygulama vardır ve her durum için elverişli için böyle bir tarzı optimize sert sorun olduğunu.


Lütfen SO sorusu ile bu soru arasındaki önemli farka dikkat edin. SO neden her şeyi zaman uyumsuz hale getirmediğini sorar. Burada bunu önermiyoruz, sadece% 10'luk eşzamansız, sadece aynı sözdizimini kullanmanızı öneririz. Daha yakın bir sözdizimi kullanmanın avantajı, bu değişikliklerden domino efektleri çekmeden% 10'unun async olduğunu daha kolay bir şekilde değiştirebilmenizdir
talkol

Neden asynczombi istilası üreteceğinden biraz emin değilim . Bir yöntem başka 10 yöntem çağırsa bile async, üst düzey olana ihtiyacınız yok mu?
Robert Harvey

6
Mevcut kodumun% 100'ünün senkronize olduğunu varsayalım. Şimdi zaman uyumsuz değiştirmek istediğiniz DB sorgulayan tek bir iç yaprak düzeyi işlevi var. Şimdi async yapmak için onun arayan async ve onun arayan async, vb gerekir üst seviyeye kadar. Tabii ki tüm zincirin beklendiği durumdan bahsediyorum (kodun senkron tasarımını tutmak veya dönüş değerlerini geçmek için)
talkol
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.