2014-06-26 28 views
13

Task<T> düzgünce "başlatılmış, tamamlanmış olabilir" hesaplamasını, diğer görevler, işlevler ile eşleştirilen vb. Ile birlikte oluşturabilir. Buna karşılık, F # async monad "daha sonra başlayabilir, şimdi çalışıyor olabilir" hesaplama ve CancellationToken ile birlikte . C# 'da, genellikle Task ile çalışan her işlev aracılığıyla CancellationToken iş parçacığı. C# takımı neden hesabı Task monad'ına sarmayı seçti, ama CancellationToken?Task <T> Monad'da neden bir CancellationToken bulunmuyor?

+2

C# içinde, "var görev = yeni Görev (eylem, simge)" biçiminde bir CancellationToken * seçeneğiyle birlikte *, "daha sonra başlayabilir, şimdi çalışıyor olabilir". – Noseratio

cevap

9

Daha çok veya daha azı, C# async yöntemleri için CancellationToken örtük kullanımını kapsüllediler. Şunu bir düşünün: zaman uyumsuz olmayan lamda için

var cts = new CancellationTokenSource(); 
cts.Cancel(); 
var token = cts.token; 

var task1 = new Task(() => token.ThrowIfCancellationRequested()); 
task1.Start(); 
task1.Wait(); // task in Faulted state 

var task2 = new Task(() => token.ThrowIfCancellationRequested(), token); 
task2.Start(); 
task2.Wait(); // task in Cancelled state 

var task3 = (new Func<Task>(async() => token.ThrowIfCancellationRequested()))(); 
task3.Wait(); // task in Cancelled state 

, ben iptal new Task() (veya Task.Run) bir argüman olarak vererek, doğru yaymak için açıkça task2 ile token ilişkilendirmek zorunda kaldı. task3 ile kullanılan bir async lambda için, async/await altyapı kodunun bir parçası olarak otomatik olarak gerçekleşir. uyumsuz olmayan hesaplama new Task()/Task.Run lambda için görev kurucu veya Task.Run geçirilen aynı belirteci olmak zorunda ise

Ayrıca, herhangitoken, bir async yöntem için iptal yaymak olacaktır. Kooperatif iptal modelini uygulamak için elbette el ile token.ThrowIfCancellationRequested()'u aramak zorundayız. C# ve TPL takımlarının neden bu şekilde uygulamaya karar verdiklerini söyleyemem ama sanırım, async/await'un sözdizimini aşırı derecede karmaşıklaştırmayı değil, yeterince esnek tutmayı amaçlıyorlardı.

F # ile ilgili olarak, Tomas Petricek'in bağlı olduğunuz blog post resminde gösterilen zaman uyumsuz iş akışının oluşturulmuş IL kodunu incelemedim. Yine de, anlayabildiğim kadarıyla, token otomatik olarak yalnızca iş akışının belirli noktalarında test edilir, bunlar C# 'da await'a karşılık gelir (analojiyle, token.ThrowIfCancellationRequested()'u her # await C#' da el ile çağırıyor olabiliriz). Bu, CPU'ya bağlı herhangi bir işlemin hemen iptal edilmeyeceği anlamına gelir. Aksi halde, F #, her IL talimatından sonra token.ThrowIfCancellationRequested() yaymak zorunda kalacaktır, ki bu oldukça önemli bir ek yük olacaktır.

+0

CPU'ya bağlı iş için ne zaman ve neden beklemede/beklemede bulunmak istersiniz? – GregC

+1

@GregC, her zaman bir UI uygulamasında CPU-bağlı çalışma yapmam gerekiyor: 'var pi = Task.Run (() => CalcPi (basamak, jeton), belirteç)'. – Noseratio

+1

@GregC Bir paralelleştirme şeklidir. 'Bekle. Görev.Yani (görevler)'. – Aron

2

Görev başlangıçta sınıfta ek özellikler içerecek şekilde yapıldı, ancak daha sonra ek özellik desteği ile bir nesneyi toplamak için değiştirildi. Hepsi performans adına.

http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235962.aspx (kağıda "yeniden yapılanma görevi" konusuna bakın) Joseph E. Hoag tarafından hazırlanan makale, .NET 4.5'te yapılan en iyileştirmelerle ilgili güzel bilgiler verir. Async/beklemedeki performansın son% 10'unu sıkıştırmaya çalışan herkes için iyi bir okuma olacağını düşünüyorum.

İptal işlevinin nasıl paketleneceğine karar verirken benzer bir düşünce işlemi uygulandığını farz ediyorum.

C# veya BCL ekibi için konuşamıyorum, ancak bunun yalnızca F # derleyicisinde mümkün olan bir performans optimizasyonu olduğunu veya performansın F # ekibine önemsiz olduğunu varsayıyorum. SRP, baby!

+1

O Hoag gazetesini unutmuştum. Sürüş gibi göründüğü gibi Task nesnesini mümkün olduğunca küçük tutmak, bu nedenle İptal belirteci etrafında taşımak değil, bunun yerine async/beklemenin oluşturduğu durum makinesinde taşımaktı. –

İlgili konular