2012-04-22 18 views
7

MSDN Documentation TaskFactory.StartNew'a göre, Görev oluşturur ve başlatır. Yani, aşağıdaki kod örneği için My beklenen çıkışı oNeden TaskFactory.StartNew Görev hemen başlamıyor?

Invoked tasks 
Invoking calculation for 20 
Invoking calculation for 10 
21 
11 
görüntülüyor,
class Program 
{ 
    public static void Main() 
    { 
     var t =Task.Factory.StartNew(
       () => SomeLongRunningCalculation(10, Display) 
      ); 
     var t1 = Task.Factory.StartNew(
       () => SomeLongRunningCalculation(20, Display) 
      ); 
     Console.WriteLine("Invoked tasks"); 
     Task.WaitAll(t, t1); 
     Console.ReadLine(); 
    } 

    public static void Display(int value) 
    { 
     Console.WriteLine(value); 
    } 

    public static void SomeLongRunningCalculation(int j, Action<int> callBack) 
    { 
     Console.WriteLine("Invoking calculation for {0}", j); 
     System.Threading.Thread.Sleep(1000); 
     if (callBack != null) 
     { 
      callBack(j + 1); 
     } 
    } 
}  

Invoking calculation for 10 
Invoking calculation for 20 
Invoked tasks 
11 
21 

oldu Ama

ben öğrenmek istiyorum

  1. Neden StartNew'den sonra görevler hemen çalışmıyor?
  2. Çıktının beklenen biçimde elde edilmesi için ne yapmalıyım?

cevap

10

Bu, tek çekirdek işlemci içeren bir makinede çok olası bir sonuçtur. Ya da bir çok çekirdekli işlemci ile mümkündür ve başka bir şey yapmakla da meşgul.

Bir görev veya iş parçacığı oluşturmak, yalnızca kodun çalışmasını sağlayan mantıksal bir işletim sistemi yapısı oluşturur. İşletim sistemi zamanlayıcısı, numaralı 'u değil, çekirdekler meşgulse hemen çalıştırmaya başlar, iş parçacığı, makinede çalışan tüm diğer iş parçacıkları ile rekabet etmelidir. Tipik bir Windows oturumu bin ya da öylesine vardır. Saniyede 64 kez, çekirdek bir kesilme oluşturur ve zamanlayıcı, başka bir iş parçacığının dönüş yapıp yapmamasını görmek için neler olduğunu yeniden değerlendirir. Engellemeyen herhangi bir ileti (bir dosya veya ağ paketi okumak gibi bir işin yapılması için başka bir iş parçacığının beklenmesi) çalışabilir ve programlayıcı en yüksek önceliğe sahip olanı seçer. Zamanlayıcıdaki bazı ek kodlar, tüm iş parçacıklarının bir şans elde etmesini sağlamak için öncelik değerleriyle birlikte çalışır.

Burada anahtar kelime şanstır. İş parçacığı zamanlaması, deterministik olmayan dur.

Konu veya Görev veya ThreadPool sınıfı hakkında hiçbir zaman nasıl bir şey söylemediğimi unutmayın. İşletim sistemi iş parçacığı zamanlama yöntemi hakkında çok şey yapma gücüne sahip değiller. Tüm bunlar 'u iş parçacığı iş parçacığı, iş parçacığı havuzu zamanlayıcısı işini engeller.

Öncelikli konular, sonucu etkilemek için Thread.Priority veya Task.Priority özelliği ile uğraşabilirsiniz. Ancak slamdunk, işletim sistemi zamanlayıcısı, bir iş parçacığı önceliğini, o özellikle ayarladığınız temel öncelikten sürekli olarak ayarlar. Örneğin, daha yüksek önceliğe sahip başka bir numaraya sahip olarak çalışan numaralı bir numaralı iş parçacığının çalışmasını engelleyemezsiniz.

Bu iş parçacığının tahmin edilebilir bir sırayla çalıştırılması, en kötü hata türüne neden olur; En kötü ikinci ise kilitlenme. Hata ayıklama yapmak çok zor çünkü zamanlamaya ve mevcut makine kaynaklarına ve yüke bağlı. Yalnızca, açıkça ilgilenen bir kod yazarak belirli bir sipariş aldığınızdan emin olabilirsiniz. Mutex veya anahtar kelimesi gibi bir ilkel ipucu kullanarak yaptığınız. Ayrıca, bu kodu kod snipp'inize eklemeyi denediğinizde, artık eşzamanlı olmayan bir programla sonuçlanacaksınız. Ya da başka bir deyişle, artık bir Görev için herhangi bir kullanımınız olmayacak. Bir iş parçacığı veya görev, yalnızca 'un'un öngörülemeyen zamanlarda çalışmasını sağlayabiliyorsa yararlı olacaktır.

+0

+1. – Ramesh

7

Neden StartNew'den sonra görevler hemen çalışmıyor? MSDNStartNew() olacak zamanlama yürütülmesi için bir görev ile ilgili

. StartNew çağrılması

onun kurucular birini kullanarak Görev oluşturarak ve ardından yürütülmesi için vaktine Başlat çağırarak işlevsel eşdeğerdir. Ancak, oluşturma ve zamanlama ayrılmadan önce StartNew, hem basitlik hem de performansı için önerilen yaklaşımdır.

TPL ThreadPool iş parçacıklarını kullandığı için - bazen belirli bir görev yürütme için bir ThreadPool iş parçacığı ayırmak ve başlatmak için bazı işler yapmak zorundadır. TPL'nin TaskScheduler'ı gibi herhangi bir ara mekanizma olmaksızın ayrı bir iş parçacığı çalıştırmanız gerekiyorsa - el ile bir iş parçacığı oluşturun ve başlatın ve devam ederek devam eden gibi düzgün bir işiniz olmayacaktır.

0

Konu veya Görev veya ThreadPool sınıfı hakkında hiçbir zaman nasıl bir şey söylemediğimi unutmayın. işletim sistemi iş parçacığı konuları hakkında çok fazla şey yapma gücüne sahip değiller. Bu mümkün olan her şey iş parçacığı, iş parçacığı havuzu zamanlayıcısı işini engeller.

Savaş ... Görevler vs Konular ... Gerekli göreve bağlı.

Örnek için, 100 istemciden (bir istemci için bir döşeme) harita döşemesi yapmak için 100 eşzamanlı görev (bir istemci için bir görev) ile Internet'ten 100 resim yüklemeliyiz. Ortak bir zaman sınırımız var ve bazı yükleme görevlerinin yüklenme süresi ortak zaman sınırlamasıyla çakışabilir. Basit test, 100 Görevlerin (sınıf Görevinin) yürütülmesi yerine, 100 Görevlerin (sınıf iş parçacığının) sınırlı bir süre için eşzamanlı yürütülmesini, çok daha verimli olduğunu gösterir. 10 Threads vs 10 Tasks için aynı sonuç. Yani "biraz durgun" dan daha fazlasına, ancak sağlam, görevlere, yani eşzamanlı görevlerde çok daha fazla çalışmaya ihtiyacımız varsa, o zaman derslik Thread'i kullanmalıyız. "Thread scheduling deterministic." Ifadesini görüntülemek için