2011-09-28 42 views
11

Standart BeginRead ve EndRead yöntemlerini TcpClient'ten kullanırken ve Task.Factory.FromAsync kullanarak çok benzer bir kodum var.Task.Factory.FromAsync ve BeginX/EndX arasındaki fark nedir?

İşte bazı örnekler .. Hata kodu gösteriliyor hatası gösterilmiyor.

Task.Factory.FromAsync: BeginRead ve EndRead ile geri aramaları

private void Read(State state) 
{ 
    Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRead, state.Bytes, state.BytesRead, state.Bytes.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent); 

    read.ContinueWith(FinishRead); 
} 

private void FinishRead(Task<int> read) 
{ 
    State state = (State)read.AsyncState; 

    state.BytesRead += read.Result; 
} 

Standart kullanım:

private void Read(State state) 
{ 
    client.BeginRead(state.Bytes, state.BytesRead, state.Bytes.Length - state.Bytes.Read, FinishRead, state); 
} 

private void FinishRead(IAsyncResult async) 
{ 
    State state = (State)async.AsyncState; 

    state.BytesRead += state.Stream.EndRead(async); 
} 

Bunların her ikisi de iyi çalışıyor ama onların farklılıklarının merak ediyorum. Her ikisi için kod satırları hemen hemen eşdeğerdir ve her ikisi de aynı işlevi yerine getirir ve aynı verime sahiptir. Hangisi tercih edilir? Üretim kodunda ne görmek istersiniz?

cevap

14

Ben daha çok Task<T> tabanlı kod görecekti:

Daha kolay kompozisyon sağlar
  • ; örneğin, Task<T> görevlerini toplayan ve bu görevlerin çoğunluğunu temsil eden başka bir görevi döndüren bir yöntem yazmak oldukça kolaydır. Benzer şekilde, herhangi bir görev koleksiyonu tamamlanana kadar bekleyebilirsiniz, vb.
  • Devamın çalıştığı yerde daha esnek bir zamanlama sağlar.
  • Görevin kendisinin tür güvenliği ve BeginRead tarafından döndürülen biraz anemik IAsyncResult10 türünden çok daha fazla bilgi ile döndürülmesine izin verir.
  • Başlatma/Sonlandırma modelini kullanmaktan ziyade, hata işleme ve iptal işlemlerini belirtmek daha kolay. Temelde Modern kod üzerinde çalışan bu

yararlanmak için kod temeli zaten yaygın bir Task<T> kullanıyorsa, o çok daha kolay olacak -

  • Task<T> zaman uyumsuz/bekliyoruz ile C# 5'de iyi dil desteği oluyor .NET 4, Task<T>, devam eden bir görevi temsil etmenin deyimsel yoludur. Daha önceki girişimlerden çok daha zengin bir ortam var ve eğer şansınız varsa onu kucaklayacağım. Açıkçası, .NET 3.5 veya daha erken kullanıyorsanız, hayat biraz daha zor, ama ben soru sorduğunda, Task<T> bir seçenek olduğunu varsayarak ...

  • +1

    Cevabınız için teşekkürler! Yine de biraz kafam karıştı. BeginRead'in çok verimli olduğunu biliyorum çünkü geri arama engelleme yerine bir IO tamamlama portu kullanıyor. ContineWith aynı verimlilik açısından aynı mıdır ve aynı zamanda sadece aynı anda çalışır EndRead koştu? Ayrıca, daha iyi hata işlemeyi nasıl desteklediğini detaylandırır mısınız? Aynı zamanda her bir kod örneğindeki "state.BytesRead + =" satırlarında da aynı denemeyi yapmak zorunda kalmaz mıyım? –

    +2

    @RyanPeschel: Evet, engellemez - aksi takdirde anlamsız olur. Ve hayır, aynı deneme/yakalamaya ihtiyacınız olmazdı, çünkü hata üzerinde çalıştırmak için bir devamlılık, iptalde bir diğeri de başarıya ulaşmak için başka bir tane belirtebilirsiniz - ContinueWith için aşırı yüklenmelere bakın. Ayrıca, yalnızca sonuca ulaşmaya çalışmaksızın bir görevin durumunu * test edebilirsiniz (Task.Status'a bakın). Her şey temelde çok daha zengin. Ve C# 5'deki async desteği harika. –

    +0

    Aşırı yükleri kontrol ediyorum ama ne elde ettiğinizi göremiyorum. Hata/iptal olduğunda çalıştırılacak bir yöntemi nasıl belirleyebilirim? –

    İlgili konular