private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
Düzenle
Popüler talep nedeniyle, Task
başlatılanın arayan iş parçacığı ile paralel çalışacağını not etmeliyim . Varsayılanı varsayarsak TaskScheduler
bu .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 async
ve 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 await
oluş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, await
aramadan 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 Task
size iletilen parametrelere erişmezse , hiç kullanmak istemeyebilirsiniz await
.
Ya da belki bu parametreleri yöntemde çok daha sonra kullanırsınız. await
Güvenli bir şekilde çalışmaya devam edebileceğiniz için hemen gerek yok . Unutmayın, Task
döndürülenleri bir değişkende ve await
daha 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 Task
bunu ç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
Task
Task<TResult>
async
Şimdi aşağıdaki gibi await
çalıştırabilirsiniz Task
. await
Onsuz kullanamazsınız async
.
await Task.Run(() => MethodWithParameter(param));
Bu nedenle, genel olarak, eğer await
gö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 await
hiç 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 lock
WinForms 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.