2017-11-12 143 views
5

Özellikle async/await hakkında daha fazla bilgi edinmek istiyorum ve özellikle derleyicinin ek bir iş parçacığı oluşturmaksızın async yönteminde ve await'da "duraklat" yöntemini nasıl bildiğini öğreniyorum.Bir C# derleyicisi bir async yöntemini ne zaman keseceğini biliyor?

Örnek olarak

, en ı await sqlConnection.OpenAsync(); benim yöntemi "askıya" alır nerede olduğunu biliyoruz

DoSomeStuff(); 
await sqlConnection.OpenAsync(); 
DoSomeOtherStuff(); 

gibi bir async yöntemi ve iplik havuzuna döner çağrılan iş parçacığı ve bir kez Task var diyelim Bu, bağlantı açıklığının takibini tamamlarsa mevcut bir iş parçacığının DoSomeOtherStuff() çalıştırdığı bulunur.

| DoSomeStuff() | "start" opening connection | ------------------------------------ | 
| ---------------------------------------------------------- | DoSomeOtherStuff() - | 

Burada kafam karıştı. Ben OpenAsync (https://referencesource.microsoft.com/#System.Data/System/Data/Common/DBConnection.cs,e9166ee1c5d11996,references) kaynak koduna bakıp ben görev harici bir kaynak ile iletişim başladı çünkü derleyici ipliği "kesti" için bilemez bazı yeri görmek hayal

public Task OpenAsync() { 
     return OpenAsync(CancellationToken.None); 
    } 

    public virtual Task OpenAsync(CancellationToken cancellationToken) { 
     TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>(); 

     if (cancellationToken.IsCancellationRequested) { 
      taskCompletionSource.SetCanceled(); 
     } 
     else { 
      try { 
       Open(); 
       taskCompletionSource.SetResult(null); 
      } 
      catch (Exception e) { 
       taskCompletionSource.SetException(e); 
      } 
     } 

     return taskCompletionSource.Task; 
    } 

, ama Bunu gerçekten görmüyorum ve aslında, Open();, eşzamanlı olarak beklediğini ima ediyor gibi görünüyor. Birisi bunun nasıl "hatasız" gerçek "kodsuz" kod haline geldiğini açıklayabilir mi?

+3

Eh, openAsync böyle uygulama aslında "gerçek zaman uyumsuz" kodu değil. – CodeFuller

+0

C# derleyicisi bir gizli sınıfın * iki * yöntemlerle dönüşür kodunuzu yeniden yazar. DoSomeOtherStuff() çağrısı ikinci yöntemdedir. Her iki parçada sahip olabileceğiniz ve kullanabileceğiniz yerel değişkenler bu sınıfın alanları olur. Ildasm.exe yardımcı programını kullanarak görebileceğiniz bir şey. –

+0

@CodeFuller Eğer openAsync bir "gerçek zaman uyumsuz" uygulamasının bir örneği() için işaret edebilir? Ya da yukarıdaki OpenAsync() 'in gerçek zamanlı senkronize olarak nasıl yazılabileceğini göster? – Questionaire

cevap

5

gerçeğinden aşağıdaki

await sqlConnection.OpenAsync(); 

serbest bırakılacağı ve ait olduğu iş parçacığı havuzundan tarafından kullanılmak için kullanılabilir olacaktır denilen iplik async-beklemektedir sonuçları kullanmanın avantajı. Bir ASP.NET uygulaması hakkında konuşuyorsak, iş parçacığı serbest bırakılacak ve başka bir gelen HTTP isteğine hizmet etmek için kullanılabilir olacaktır. Bu şekilde, ASP.NET iş parçacığı havuzunun iş parçacıkları HTTP isteklerini hizmet etmek için her zaman kullanılabilir olur ve örneğin bir veritabanına bağlantı açma ve bazı SQL deyimlerini yürütme gibi bir G/Ç için engellenmez.

Güncelleme

Size await olacak Görev tamamlanmıştır eğer, kodunuz eşzamanlı aday olacağını burada belirtilmelidir.

+0

Sizin ikinci paragraf, _Regarding Açık() _, 'Aç()' Bir arka plan iş parçacığı üzerinde çalıştırmak için gerekli değildir olarak yanıltıcıdır. Gösterilen uygulama senkronize ve tek başına bağlam değiştirmez. 'OpenAsync' ve' Open' aynı bağlamda çalışır ve çağrıyla ilişkilendirilen tek thread'ı engeller. – JSteward

+0

@JSteward Argümanınızın doğru olduğundan emin değilim. Burada belirtildiği gibi https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/await *** Bir bekletme ifadesi, üzerinde çalıştığı parçayı engellemez **. Bunun yerine, derleyici beklenen asim yönteminin geri kalanını, beklenen görevde bir devamı olarak kaydettirir. Kontrol daha sonra async metodunun arayıcısına döner. Görev tamamlandığında, onun devamı çağırır ve kaldığı yerden zaman uyumsuz yönteminin yürütme devam eder. * Ayrı bir iş parçacığı çalışacağı bu beklenir Görev bütün kod. – Christos

+0

Bu davranış, yalnızca "Görev/Görev " döndürme yönteminin uygulanmasının gerçek bir eşzamansız yöntem oluşturup uygulamaması durumunda uygulanır. Uygulama senkronize ve engelleniyorsa; 'bekliyor', işi otomatik olarak başka bir içeriğe taşımayacaktır. Engelleme uygulaması, beklenen bir dönüş türüne bakılmaksızın her zaman engellenir. – JSteward

6

Sizin yönteminiz beklemede "askıda" olmaz. Beklediğiniz görev zaten tamamlandıysa (sağladığınız koddaki durum) - yöntem her zamanki gibi devam edecektir. DbConnection taban sınıfı ve yöntem OpenAsync sanal olduğu için, baktığınız yöntem gerçekten SqlConnection tarafından kullanılan değil. SqlConnection, geçersiz kılar ve gerçek zaman uyumsuz uygulama sağlar. Bununla birlikte, tüm sağlayıcılar bunu yapmaz ve gerçekten de sorgunuzda gösterdiğiniz uygulamayı kullanmazlar. Bu tür bir uygulama kullanıldığında - her şey herhangi bir diş anahtarı olmadan eş zamanlı olarak çalışacaktır. Eğer

public async Task Do() { 
    DoSomeStuff(); 
    await sqlConnection.OpenAsync(); 
    DoSomeOtherStuff(); 
} 

var Ve OpenAsync gerçek zaman uyumsuz sürümü sağlamaz sağlayıcı kullanmak varsayalım. Sonra birisi await Do() aradığında - arama iş parçacığı tüm işi gerçekleştirir ( DoSomeStuff, OpenAsync, DoSomeOtherStuff). Bu UI iş parçacığı ise - tüm süre boyunca engellenir (bu tür durumlar genellikle insanların UI iş parçacığı üzerinde çalışmaya başlayacağını varsayarak bu tür sağlayıcılar için bu tür sağlayıcılar için "async" yöntemlerini kullandığında oluşur).

+0

Bana "OpenAsync()" true async "uygulamasının bir örneğini işaret edebilir misiniz? – Questionaire

+0

@Questionaire, SqlConnection kaynak kodudur: http: //referencesource.microsoft.com/#System.Data/System/Data/SqlClient/SqlConnection.cs – Evk

+0

@Questionaire gerçek asenkron genellikle senkronize olmayan IO'dur (dosyalar, yuvalar). https://blog.stephencleary.com/2013/11/there-is-no-thread.html: Bu okuma ilgini çekebileceğini – Evk

İlgili konular