private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
Düzenle
Popüler talep nedeniyle, Taskbaşlatılanın arayan iş parçacığı ile paralel çalışacağını not etmeliyim . Varsayılanı varsayarsak TaskSchedulerbu .NET'i kullanacaktır ThreadPool. Her neyse, bu Task, potansiyel olarak aynı anda birden fazla iş parçacığı tarafından erişilen parametre (ler) i hesaba katmanız gerektiği anlamına gelir, bu da onları paylaşılan durum haline getirir. Bu, onlara çağrı iş parçacığı üzerinden erişmeyi içerir.
Yukarıdaki kodumda bu durum tamamen tartışmalı. Dizeler değişmezdir. Bu yüzden örnek olarak kullandım. Ama kullanmadığınızı söyleyin String...
Bir çözüm kullanmaktır asyncve await. Bu, varsayılan olarak, SynchronizationContextçağıran iş parçacığının yakalanmasını sağlar ve çağrıldıktan sonra yöntemin geri kalanı için bir devamlılık awaitoluşturur ve onu oluşturulana ekler Task. Bu yöntem WinForms GUI iş parçacığında çalışıyorsa, türünde olacaktır WindowsFormsSynchronizationContext.
Devam etme, yakalanan kişiye geri gönderildikten sonra çalıştırılacaktır SynchronizationContext- yine yalnızca varsayılan olarak. Böylece, awaitaramadan sonra başladığınız konuya geri döneceksiniz . Bunu, özellikle kullanarak çeşitli şekillerde değiştirebilirsiniz ConfigureAwait. Kısacası bu yöntemin geri kalanı kadar devam etmeyecek sonraTask başka iş parçacığı üzerinde tamamladı. Ancak çağıran iş parçacığı, yöntemin geri kalanı değil, paralel olarak çalışmaya devam edecektir.
Yöntemin geri kalanının tamamlanmasını beklemek istenebilir veya istenmeyebilir. Bu yöntemde hiçbir şey daha sonra Tasksize iletilen parametrelere erişmezse , hiç kullanmak istemeyebilirsiniz await.
Ya da belki bu parametreleri yöntemde çok daha sonra kullanırsınız. awaitGüvenli bir şekilde çalışmaya devam edebileceğiniz için hemen gerek yok . Unutmayın, Taskdöndürülenleri bir değişkende ve awaitdaha sonra aynı yöntemde bile saklayabilirsiniz . Örneğin, bir sürü başka iş yaptıktan sonra aktarılan parametrelere güvenli bir şekilde erişmeniz gerektiğinde. Yine, do not gerekir awaitüzerinde Taskbunu çalıştırdığınızda sağ.
Her neyse, bu iş parçacığını, iletilen parametrelere göre güvenli hale getirmenin basit bir yolu Task.Run, bunu yapmaktır:
Önce RunAsyncşununla süslemelisin async:
private async void RunAsync()
Önemli Not
Bağlantılı belgelerde bahsedildiği gibi, işaretlenen yöntem tercihen geçersiz hale gelmemelidir . Bunun genel istisnası, düğme tıklamaları gibi olay işleyicileridir. Boşuna dönmeleri gerekir. Aksi takdirde her zaman a veya kullanırken dönmeye çalışırım . Birkaç nedenden dolayı iyi bir uygulamadır.async TaskTask<TResult>async
Şimdi aşağıdaki gibi awaitçalıştırabilirsiniz Task. awaitOnsuz kullanamazsınız async.
await Task.Run(() => MethodWithParameter(param));
Bu nedenle, genel olarak, eğer awaitgörev sizseniz, parametrelerde iletilen bir şeyi aynı anda birden çok iş parçacığından değiştirmenin tüm tuzaklarına sahip, potansiyel olarak paylaşılan bir kaynak olarak ele almaktan kaçınabilirsiniz. Ayrıca, kapanışlara dikkat edin . Bunları derinlemesine ele almayacağım ama bağlantılı makale harika bir iş çıkarıyor.
Kenar notu
Biraz konu dışı, ancak ile işaretlendiğinden WinForms GUI iş parçacığında herhangi bir "engelleme" türü kullanırken dikkatli olun [STAThread]. Kullanmak awaithiç engellemez, ancak bazen bir tür engelleme ile birlikte kullanıldığını görüyorum.
"Blok" tırnak içinde çünkü teknik olarak WinForms GUI iş parçacığını engelleyemezsiniz . Evet, kullanmak durumunda lockWinForms GUI üzerinde o iplik olacak hala en "engellenmiş" düşüncesiyle rağmen iletileri pompalamak. Değil.
Bu, çok nadir durumlarda tuhaf sorunlara neden olabilir. lockÖrneğin, resim yaparken asla kullanmak istememenizin nedenlerinden biri . Ancak bu uç ve karmaşık bir durumdur; ancak bunun çılgın sorunlara neden olduğunu gördüm. Bu yüzden bütünlük uğruna not ettim.