Senkronizasyon ve asenkron yöntemlerin tek bir yöntemde verimli bir şekilde karıştırılması?


11

Tamam, kulağa garip geliyor, ancak kod çok basit ve durumu iyi açıklıyor.

public virtual async Task RemoveFromRoleAsync(AzureTableUser user, string role)
{
    AssertNotDisposed();
    var roles = await GetRolesForUser(user);
    roles.Roles = RemoveRoles(roles.Roles, role);
    await Run(TableOperation.Replace(roles));
}

(Aşağıdaki özette biraz bahsettiğimi biliyorum, ama yukarıdaki gerçek üretim kodunun ne olacağından gerçek bir yöntem. zaman uyumsuz / beklemede bir doğruluk için.)

async/ awaitDaha fazla kullandığım için bu model ile daha sık karşılaşıyorum . Desen aşağıdaki olay zincirinden oluşur:

  1. Çalışmam gereken bazı bilgileri bana getiren ilk aramayı bekliyor
  2. Bu bilgiler üzerinde eşzamanlı çalışma
  3. Güncellenmiş çalışmayı kaydeden son bir çağrı beklemek

Yukarıdaki kod bloğu genellikle bu yöntemleri işleme hakkında nasıl olduğunu. Ben awaitbunu asenkron olduğundan gereken ilk çağrı. Sonra, IO veya kaynak bağlı olmayan ve bu nedenle zaman uyumsuz olmayan yapmam gereken işi yapıyorum. Sonunda, aynı zamanda bir asyncçağrı olan işimi saklıyorum ve kargo kültünden çıkarıyorum await.

Ancak bu, bu modeli ele almanın en etkili / doğru yolu mu? Bana öyle geliyor ki awaitson çağrıyı atlayabilirim , ama başarısız olursa? Eşzamanlı çalışmamı orijinal çağrı ile zincirlemek için bir Taskyöntem kullanmalı ContinueWithmıyım? Şu anda bunu doğru bir şekilde ele alıp almadığımdan emin olmadığım bir noktadayım.

Örnekteki kod verildiğinde, bu async / sync / async yöntemi çağrı zincirini işlemenin daha iyi bir yolu var mı?


Kod bana mümkün olduğunca kısa ve anlaşılabilir görünüyor. Aklıma gelen her şey gereksiz karmaşıklık getiriyor.
Euphoric

@Euphoric: Son aramamı beklerken rahatsız etmeli miyim? Eđer yapmasaydým ne olur? Şu an olduğu gibi farklı olabilir mi?
Off Rip

Yanıtlar:


3

Evet, bunu yapmanın doğru yolu olduğunu düşünüyorum.

İkincisini atlayamazsınız await. Bunu yaptıysanız, yöntem çok erken tamamlanmış gibi görünecektir (kaldırma işlemi gerçekten yapılmadan önce) ve kaldırma işleminin başarısız olup olmadığını asla öğrenemezsiniz.

ContinueWith()Burada nasıl yardımcı olabileceğini veya böyle bir şey göremiyorum . Kullanmaktan kaçınmak için kullanabilirsiniz await, ancak kodunuzu daha karmaşık ve daha az okunabilir hale getirir. Ve tüm mesele bu await: süreklilik kullanımıyla karşılaştırıldığında, zaman uyumsuz kod yazmayı kolaylaştırmak.


0

Bu modeli ele almanın yolu, tüm G / Ç'nin asenkron olmasını sağlamaktır. Eşzamanlı G / Ç yöntemleri, G / Ç hedefinden (ağ, dosya sistemi, vb.) Bir yanıt beklerken geçerli iş parçacığının engellenmesine neden olur.

Dikkate alınması gereken başka bir şey, awaitbir dönüş değerine ihtiyacınız olduğunda veya başka bir şey yapmadan önce bitirmek için beklenen koda ihtiyacınız olduğunda kullanılmasıdır. Bunlardan herhangi birine ihtiyacınız yoksa, zaman uyumsuz yönteminizi "tetikleyebilir ve unutabilirsiniz" Task.Run.

Bu nedenle, bilgi işlem kaynaklarının en verimli kullanımı için, RemoveRolesherhangi bir G / Ç varsa, bu olmalı await RemoveRolesAsyncve çağrılan G / Ç yöntemleri RemoveRolesAsyncde zaman uyumsuz (ve muhtemelen beklenir) olmalıdır.

Performans en büyük endişeniz değilse, zaman uyumsuz bir iş parçacığında senkronize bir G / Ç yapmak iyidir. Yine de teknik bir borçtur. (Bu durumda, belki ilk zaman uyumsuz yöntemini aramak istediğiniz ConfigureAwaitkod çalıştığı yere bağlı olarak.)

En iyi uygulamalara daha ayrıntılı bir bakış - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

ASP.NET, WebAPI vb.Gibi farklı ortamlarda ConfigureAwait'in davranışı hakkında bazı notlar - /programming/13489065/best-practice-to-call-configureawait-for-all-server-side -Kod


2
Görevle asla ateş etmemeli ve kodu unutmamalısınız. Tüm görevler beklenmelidir. Görevi beklemezseniz ve Görev, istisnanın "gözlenmediği" durumda çöp toplanırsa, çalışma zamanında bir UnobservedTaskException özelliğinin kaldırılmasına neden olur ve çerçeve sürümüne bağlı olarak uygulamanızı kilitleyebilir.
Triynko
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.