2016-10-18 15 views
13

.Net WPF uygulamasındaki bekleme/uyumsuzluk mekanizmasını kullanmaya başladım.En iyi uygulamalar bekle-uyumsuzluğu, görevi başlatmak için nerede kullanılır?

ViewModel'de bir hizmette async yöntemini arıyorum.

Sorum şu: it Bu hizmetin iç Doğrudan

  1. mı iyidir, yapmak büyük bir return await Task.Run(()=>{...});
  2. bu hizmette tüm submethods da zaman uyumsuz olması ve sonra bu Task.Run var içeride mı?

    1)

    public class Service:IService{ 
        public async Task<SomeResult>(SomeParameter parameter){ 
         return await Task.Run(()=>{ 
          CopyStuff(parameter.A); 
          UpgradeStuff(parameter.B); 
          return ReloadStuff(parameter.C) 
         }); 
        } 
    
        private void CopyStuff(ParamA parameter){ 
         ...//Some long operation that will mainly wait on the disk 
    
        } 
        private void UpgradeStuff(ParamB parameter){ 
         ...//Some long operation that should not block the GUI thread 
        } 
        public SomeResult ReloadStuff(ParamC parameter){ 
         return ...;//Some long operation that relaunch some services and return their successs  
        } 
    } 
    

    2) her iki yaklaşım avantaj görebilir

    public class Service:IService{ 
        public async Task<SomeResult>(SomeParameter parameter){ 
         await CopyStuff(parameter.A); 
         await UpgradeStuff(parameter.B); 
         return await ReloadStuff(parameter.C)  
        } 
    
        private async Task CopyStuff(ParamA parameter){ 
         return await Task.Run(()=>{...});//Some long operation that will mainly wait on the disk 
        } 
        private async Task UpgradeStuff(ParamB parameter){ 
         return await Task.Run(()=>{...});//Some long operation that should not block the GUI thread 
        } 
        public async Task<SomeResult> ReloadStuff(ParamC parameter){ 
         return await Task.Run(()=>{return ...});//Some long operation that relaunch some services and return their successs 
        } 
    } 
    

    : örnek ile

1 de

  • ) biz olacak daha az görev kullanmak Bu muhtemelen en verimli (???)
  • 2) Bu, uyumsuzluk yaklaşımıyla daha "uyumlu" hisseder, bu, bazı yöntemlerin görünürlüğünü değiştirmeye ve hala uyumsuz olmasına izin verir, bu yöntemlere izin verir Bir gün gerekirse paralel olarak koşmak.
+3

Sizin yerinizde, UI duyarlılığını yapmak için 'Task.Run' kullanmanız gerekir, değil mi? Hizmet sınıfının normal bir eşzamanlı sınıf olduğunu ve 'Task.Run' u bir kez UI'ye mümkün olduğunca yaklaştırdığınızı öneririm. Örneğin, MVVM komut işleyicilerinizde. –

+0

Sadece iki kuruşum: ikinci yaklaşımda, senkronizasyon bağlamını önemsemiyorsanız, her 'bekle 'çağrısında' ConfigureAwait (false) 'seçeneğini kullanmayı unutmayın. Çalışma zamanı, her seferinde bağlamı değiştirmeyeceğinden, size küçük bir performans artışı verir (özellikle birçok 'bekleyiş arandığında'). – dymanoid

+0

@YacoubMassad Evet, ancak bu hizmeti kullanacağım her seferinde yeni bir görev ilan etmek zorunda kalacağım ve başkalarının hiçbirine paralel olarak koşmayacakları anlamına geliyor, değil mi? – J4N

cevap

8

Hangi seçenek seçilir?

Ben senin seçeneklerin hiçbiri kullanmak

, ikisi de sahte imza arkasında yöntemler aslında bu onun zaman uyumsuz yöntemleri kullanır ama gerçek olduğunu düşünürler hizmetinizi kullanacak bir yanıltıcı API, herkesi yaratacak hiç eşzamansız değil.
Hizmetiniz, işi yalnızca yürütme sırasında engellenecek başka bir ThreadPool iş parçacığına iletir.

İstemci tarafında bu ilkeyi kullanarak sunucu tarafında o kadar da kötü görünmüyorsa, bu ilkeyi ölçeklendirebilirsiniz. Stephen Cleary göre

:

yöntemin uygulanmasında Task.Run kullanmayın; bunun yerine, yöntemi çağırmak için Task.Run kullanın.

yöntemler gerçekten senkron ise ağır yöntem zaman sen Task.Run kullanmalısınız yürütülürken UI iş parçacığı engellemek istiyor etmezseniz, sahte zaman uyumsuz imzalarla servis yöntemleri sarmak olmamalı Görünüm modelinden hizmet yöntemlerini çağırıyor.

Onun blogunda Task.Run Etiquette articles Stephen Cleary dizisini okumanızı öneririm.Böylece I inşa kullanmak düşünmelisiniz eğer

G/Ç işlemleri için zaman uyumsuz yöntemleri kullanmayı düşünün

Üstelik ben, servis yaptığı işlerde sadece CPU bağlı çalışma olduğunu görebilirsiniz G/Ç async API yöntemi, şu anda kullandığınız zaman senkronizasyon üzerinde mevcutsa (örneğin, Asynchronous File I/O), bu durumda, yöntemleriniz gerçek bir async metodu olacak ve şu anda olduğu gibi sahte bir asenkron sarmalayıcı olmayacaktır.

Eğer G/Ç zaman uyumsuz işlemi yürütmek olurken engellemez Elinden UI iş parçacığı yapacaklar, ama olursa da hala varsa ağır CPU çalışma katılan ve bağlı CPU sırasında UI engellemek istemiyoruz bağlı iş yürütme, yine de, görünüm modelinden hizmet yöntemini çağırdığınızda Task.Run kullanabilirsiniz (yöntem imzası zaten bir uyumsuz olan olsa bile).

Yukarıdaki makale dizisinde eşzamanlı ve eşzamansız yöntemlerin karışımı hakkında daha fazla bilgi.

zaman uyumsuz API yöntemlerinde Bult kullanmanın bir diğer büyük avantajı bu yöntem size do not blockThreadPool parçacığı herhangi zaman uyumsuz g/Ç işlemi yürütülüyor ve daha ThreadPool parçacığı başka işler yapmak serbest olduğu gibi zaman uyumsuz gerçekten ise.
Bu, özellikle sunucu tarafında uyumsuz programlama kullanıldığında önemlidir ve ölçeklenebilirliğinizi gerçekten artırabilir.

Async ve MVVM

Son bir şey, sen MVVM desen takip ediyorlarsa MSDN "async MVVM" articles kullanabileceğiniz harika bir okuma malzemedir.

+0

Temel olarak, çağrı yığınının async'de bulunan bir yöntemi varsa, async olarak bildirilen bir yönteme sahip olmamalı mıyım? – J4N

+1

Tür, yöntem eşzamanlı olarak uygulanmışsa, yöntem düzgün olmayan bir uyumsuzluk yaparsa, eşzamansız olarak işaretlememelisiniz. Task.Run'u yalnızca UI iş parçacığından uzun bir çalışma yöntemi çağırdığınızda ve onu engellemek istemediğinizde, yöntem uygulamasının kendisinde Task.Run'u kullanmamalısınız. – YuvShap