İş parçacığı oluşturma - Task.Factory.StartNew - new Thread ()


102

.Net 4'teki yeni Threading ve Parallel kitaplıklarını yeni öğreniyorum.

Geçmişte böyle yeni bir Konu yaratırdım (örnek olarak):

DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThread.IsBackground = true;
DataInThread.Start();

Şimdi yapabilirim:

Task t = Task.Factory.StartNew(() =>
{
   ThreadProcedure();
});

Varsa fark nedir?

Teşekkürler


1
İş parçacığı havuzu planlayıcısının nasıl çalıştığı konusunda biraz endişelenmeniz gerekecek. Bu büyük bir fark yaratabilir ama bu, iş parçacığı içinde gerçekte ne yaptığınıza bağlıdır.
Hans Passant

Yanıtlar:


79

Arada büyük bir fark var. Görevler ThreadPool'da planlanır ve hatta uygunsa senkronize olarak yürütülebilir.

Uzun süredir çalışan bir arka plan çalışmanız varsa, bunu doğru Görev Seçeneğini kullanarak belirtmelisiniz.

Daha optimize olduğu için açık iş parçacığı işlemeye göre Görev Paralel Kitaplığı'nı tercih etmelisiniz. Ayrıca Devam gibi daha fazla özelliğe sahipsiniz.


5
Hayır değil. Sadece görevleri başlatır. Bu, görevi iş parçacığı havuzunda sıraya koyabilir veya eşzamanlı olarak yürütebilir. TPL sizi iş parçacıkları / eşzamanlılığı kendiniz yönetmekten ve platformunuz için en iyisini kullanmaktan (çekirdeklerden yararlanmak gibi)
kurtarmakla ilgilidir

10
Her zaman başka bir iş parçacığı yaratacak TaskCreationOptions.LongRunning seçeneği vardır, ancak asıl mesele neden başka bir iş parçacığına ihtiyacınız var? Paralel olarak bir şey yapmak istiyorsanız (Görev çalışırken Ana yapar), optimize edilmiş bir kitaplığın bunu en verimli şekilde yapmak için iş parçacıkları gibi sistem kaynaklarını nasıl kullanacağına karar vermesine izin vermek tercih edilir.
sanosdole

3
Bu msdn makalesi, görevlerin nasıl zamanlandığını açıklar. Uzun süreli çalışmayı ve satır içi (senkron yürütme) kapsar. msdn.microsoft.com/en-us/library/dd997402.aspx
sanosdole

2
@sming Burada önemli olan nokta, yeni bir iş parçacığı istememek değil, aynı anda işlem yapmak (UI'yi engellememek) istemenizdir. ThreadPool, UI iş parçacığını engellemez, ancak arka plan iş parçacıklarını, evreler oluşturarak elle yapabileceğinizden çok daha verimli yönetir. TPL'nin getirdiği zihin sürecindeki değişiklik budur. Konuları düşünmeyin, eşzamanlı görevleri düşünün.
sanosdole

4
@sming Üzgünüm, bu cümle biraz fazla kabaydı. Görevlerin eşzamanlı olarak yürütülmesi satır içi olarak adlandırılır. UI iş parçacığından iş parçacığı havuzunda (varsayılan zamanlayıcı) bir görev zamanlarken, bu gerçekleşmeyecektir. Yalnızca ortam zamanlayıcı ('TaskScheduler.Current') '.Wait ()' olarak çağırdığınız bir görevin zamanlayıcı ile aynıysa gerçekleşir. '.Wait ()' engellediği için, yine de kullanıcı arayüzünü engelliyor olacak. Kısa: Beklemeyi çağırmayın ve eşzamanlı olarak çalıştırılmayacaktır.
sanosdole

74

Görev, size görev API'sinin tüm iyiliğini verir:

  • Devamlılıklar ekleniyor ( Task.ContinueWith)
  • Birden fazla görevin tamamlanması bekleniyor (tümü veya herhangi biri)
  • Görevdeki hataları yakalama ve daha sonra sorgulama
  • İptali yakalama (ve başlamak için iptali belirlemenize izin verme)
  • Potansiyel olarak bir dönüş değerine sahip
  • C # 5'te await kullanma
  • Zamanlama üzerinde daha iyi kontrol (uzun sürecekse, görevi oluştururken bunu söyleyin, böylece görev zamanlayıcı bunu hesaba katabilir)

Her iki durumda da, kodunuzu yöntem grubu dönüşümleriyle biraz daha basit hale getirebileceğinizi unutmayın:

DataInThread = new Thread(ThreadProcedure);
// Or...
Task t = Task.Factory.StartNew(ThreadProcedure);

8
+1. ( Ayrıntılara giren bir blog yazım var) ile Threadkarşılaştırıldığında çok düşük seviyeli olduğunu eklemek isterim . Grand Rapids DevDay'de "Görevleri gerçek dünyada kullanma" tarzında bir konuşma yapıyorum . Konuşmanın adı "İş Parçacığı Ölü", çünkü artık buna gerek yok (a uygulamıyorsanız ). TaskThreadTaskScheduler
Stephen Cleary

@StephenCleary, Threadarka plan iş parçacığı olarak kullanılmaya gelince, öldü demek istediğinizi varsayıyorum.
ebb

1
@ebb: Hayır, ilk yorumumda anlattığım daha güçlü pozisyonu alıyorum. Daha zarif ve uygun bir şekilde yapılamayacak Thread(veya BackgroundWorker) hiçbir şey yapılamaz . TaskTaskScheduler
Stephen Cleary

1
@StephenCleary, Kullanmadan özel bir iş parçacığı nasıl yaratırsınız Thread?
ebb

4
@ebb: "Adanmış konu" benim için net değil. A'nın Taskbelirli bir iş parçacığı üzerinde çalışmasını istiyorsanız , uygun bir TaskScheduler- ör., Kullanın AsyncContextThread. Ancak bu genellikle gerekli değildir; SynchronizationContext, ThreadPoolve ConcurrentExclusiveSchedulerPairschedulers çoğu program için yeterlidir.
Stephen Cleary

12

İlk durumda basitçe yeni bir iş parçacığı başlatırsınız, ikinci durumda ise iş parçacığı havuzuna girersiniz.

İş parçacığı havuzu görevi, iş parçacıklarını paylaşmak ve geri dönüştürmektir. Her yeni iş parçacığı oluşturmamız gerektiğinde birkaç milisaniye kaybetmekten kaçınmamızı sağlar.

İş parçacığı havuzuna girmenin birkaç yolu vardır:

  • ile VUK (Görev Paralel Kütüphanesi) senin yaptığın gibi
  • ThreadPool.QueueUserWorkItem çağırarak
  • Temsilci üzerinde BeginInvoke'u çağırarak
  • BackgroundWorker kullandığınızda

1

İlk kod bloğunuz CLR'ye sizin için arka plan olarak çalıştırılabilecek bir İş Parçacığı (örneğin T) oluşturmasını söyler (T'yi planlarken iş parçacığı havuzu iş parçacıklarını kullanın). Kısaca, CLR'den bir şeyler yapmanız için bir iş parçacığı oluşturmasını ve başlatmak için iş parçacığı üzerinde Start () yöntemini çağırmasını açıkça istersiniz.

İkinci kod bloğunuz aynı şeyi yapar, ancak iş parçacığı (arka plan - yine iş parçacığı havuzunda çalışır) ve Task Factory uygulamasında StartNew yöntemi aracılığıyla başlangıç ​​iş parçacığı oluşturma sorumluluğunu temsil eder (örtük olarak aktarım).

Bu, verilen kod blokları arasındaki hızlı farktır. Bunu söyledikten sonra, google veya katkıda bulunan arkadaşlarımdan gelen diğer yanıtları görebileceğiniz birkaç ayrıntılı fark var.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.