2013-07-05 8 views
5

Aşağıdaki gibi bir görev yapıyorum.Task.wait ve continueWIth

var task = Task<string>.Factory.StartNew(() => longrunningmethod() 
    .ContinueWith(a => 
      longrunningmethodcompleted((Task<string>)a, 
        TaskScheduler.FromCurrentSynchronizationContext()))); 

task.Wait(); 

Görevim longrunningmethod'u çağırır ve tamamladıktan sonra tamamlanmış yöntemi çağırır. Longrunningmethod içinde Thread.Sleep(30000) tarafından geciktiriyorum. Task.wait sistemini kullandığımda sistem askıda kalıyor ve longrunningmethodcompleted yöntemini çağırmıyor. Task.wait kullanmazsam her şey iyi akar.

+0

Bana bir kilitlenme gibi geliyor, bunu tek bir dişli ortamda yapıyor musunuz? Bunu daha önce Windows Phone geliştirme aşamasında gördüm. ([related] (http://stackoverflow.com/questions/8277291/continuation-tasks-hanging-when-using-limitedconcurrencyleveltaskscheduler)) –

cevap

12

İçeriğinizin bir kullanıcı arayüzü bağlamı olduğundan şüpheleniyorum.

Bu durumda, kilitlenmeye neden oluyorsunuz, çünkü geçerli üzerinde yürütülecek olan longrunningmethodcompleted bildiriyorsunuz.

O zaman bu bağlamı Wait numaralı telefonu arayarak engelliyorsunuz. Devam, Wait'da engellenen iş parçacığı üzerinde çalışması gerektiğinden asla tamamlanmayacaktır.

Bunu düzeltmek için, bu bağlamda devam eden bir devamında Wait kullanamazsınız. Ben longrunningmethodcompletedgerekir UI iş parçacığı üzerinde çalıştırmak için çözüm, ContinueWith çağrısı ile Wait çağrısını yerine olduğunu varsayarak yaşıyorum:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
var task = Task<string>.Factory.StartNew(() => longrunningmethod() 
    .ContinueWith(a => 
     longrunningmethodcompleted((Task<string>)a, 
     ui); 
task.ContinueWith(..., ui); 

Veya, VS2012 yükseltmek ve kullanabilirsiniz async/await , böyle daha temiz kod yazmak olanak sağlayan:

var task = Task.Run(() => longrunningmethod()); 
await task; 
longrunningmethodcompleted(task); 
+0

Teşekkürler all.Stephen Evet işe yarıyor. Ben vs2010 kullanıyorum ne yazık ki vs2012.IS için yükseltme yapamıyorum UI iş parçacığı kadar beklemek için bir iş parçacığı yapmak için bir yol ve tamamlar. – user2107843

+0

Tek seçenekleriniz, * görev zamanlayıcısı olmadan veya çalışmalarınızın geri kalanını bir devamlılık olarak sürdürmek için * süreklilikleri çalıştırmaktır. Evet, bu her türlü gerçek dünya asenkron senaryosu için çok çabuk dağınık bir hal alır. Ve bu yüzden async icat edildi. –

-1

Thread.Sleep (nnn) engelleniyor. Task.Delay (nnn) kullanın ve bekliyor:

await Task.Delay(30000); 

Düzenlendi eklemek için: Sadece etiketi Bu C# 5 ve yeni zaman uyumsuz destek bekliyor gereği C# 4. diyor kaydetti. Ciddi olarak, uyumsuzluk ve görevler yapıyorsanız, yeni sürüme geçmeniz gerekir.

+0

C# 4.0 beklemek yok – konkked

0

Eh tek bildiğim MSDN waits for the task to be completed göre ise, gerçek asynch eylemler nelerdir görmeden kodunuzdaki sorunun ne söylemek zordur. Geçerli SynchronizationContext'i eylem bloklarınızı kullanmaya çalıştığınız için mümkün mü?

Soruyorum neden olduğu için

  1. Başlangıç ​​görev
  2. Görev
  3. Görev çalışan mevcut SynchronizationContext devam etmeye çalışır (görev ile devam olan) tamamlanmasını
  4. bekleyin Bekle
  5. tamamlandıktan sonra iplik yapılması planlanan ana iş parçacığı
  6. Görev kazanmak Fakat tamamlamak için geçerli Görev bekliyor bekleyin (kilitlenme)



Demek istediğim, programınızın Thread.Sleep(seconds) ile çalışmasının nedeni, süre sınırlaması sona erdikten sonra iş parçacığı devam edecektir.

+0

Charles teşekkürler Evet anladığım kadarıyla bu kilitlenme oluştu Devam ettikten sonra Task.wait nedenim UI iş parçacığı wait.is orada yapmak için ana iş parçacığı beklemek görev kadar devam edip tamamlar. – user2107843