private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
Sunting
Karena permintaan yang populer, saya harus mencatat bahwa Task
peluncuran akan berjalan secara paralel dengan utas panggilan. Dengan asumsi default TaskScheduler
ini akan menggunakan .NET ThreadPool
. Bagaimanapun, ini berarti Anda perlu memperhitungkan parameter apa pun yang diteruskan ke yang Task
berpotensi diakses oleh beberapa utas sekaligus, menjadikannya status bersama. Ini termasuk mengaksesnya di utas panggilan.
Dalam kode saya di atas kasus itu dibuat sepenuhnya diperdebatkan. String tidak bisa diubah. Itu sebabnya saya menggunakan mereka sebagai contoh. Tetapi katakanlah Anda tidak menggunakan String
...
Salah satu solusinya adalah dengan menggunakan async
dan await
. Ini, secara default, akan menangkap SynchronizationContext
thread pemanggil dan akan membuat kelanjutan untuk metode lainnya setelah panggilan ke await
dan melampirkannya ke yang dibuat Task
. Jika metode ini berjalan di utas WinForms GUI, itu akan menjadi tipe WindowsFormsSynchronizationContext
.
Kelanjutan akan berjalan setelah diposting kembali ke yang ditangkap SynchronizationContext
- lagi hanya secara default. Jadi Anda akan kembali ke utas yang Anda mulai setelah await
panggilan. Anda dapat mengubahnya dengan berbagai cara, terutama dengan menggunakan ConfigureAwait
. Singkatnya, sisa metode yang tidak akan berlanjut sampai setelah yang Task
telah diselesaikan pada thread lain. Tetapi utas panggilan akan terus berjalan secara paralel, tidak hanya seluruh metode.
Penantian untuk menyelesaikan menjalankan sisa metode ini mungkin diinginkan atau tidak diinginkan. Jika tidak ada dalam metode itu nanti yang mengakses parameter yang diteruskan ke Task
Anda mungkin tidak ingin menggunakan await
sama sekali.
Atau mungkin Anda menggunakan parameter tersebut nanti dalam metode. Tidak ada alasan untuk await
segera karena Anda bisa terus melakukan pekerjaan dengan aman. Ingat, Anda bisa menyimpan yang Task
dikembalikan dalam variabel dan await
nanti - bahkan dalam metode yang sama. Misalnya, setelah Anda perlu mengakses parameter yang diteruskan dengan aman setelah melakukan banyak pekerjaan lain. Sekali lagi, Anda tidak perlu await
di Task
kanan saat Anda menjalankannya.
Bagaimanapun, cara sederhana untuk membuat thread ini aman sehubungan dengan parameter yang diteruskan Task.Run
adalah dengan melakukan ini:
Anda harus terlebih dahulu mendekorasi RunAsync
dengan async
:
private async void RunAsync()
Catatan penting
Lebih disukai metode yang ditandai tidak boleh kembali kosong, seperti yang disebutkan dalam dokumentasi terkait. Pengecualian umum untuk ini adalah pengendali kejadian seperti klik tombol dan semacamnya. Mereka harus mengembalikan kekosongan. Kalau tidak, saya selalu mencoba mengembalikan atau saat menggunakan . Ini praktik yang baik karena beberapa alasan.async
Task
Task<TResult>
async
Sekarang Anda dapat await
menjalankan Task
seperti di bawah ini. Anda tidak dapat menggunakan await
tanpa async
.
await Task.Run(() => MethodWithParameter(param));
Jadi, secara umum, jika Anda await
melakukan tugas tersebut, Anda dapat menghindari memperlakukan parameter yang diteruskan sebagai sumber daya yang berpotensi dibagikan dengan semua perangkap memodifikasi sesuatu dari beberapa utas sekaligus. Juga, waspadalah terhadap penutupan . Saya tidak akan membahasnya secara mendalam tetapi artikel terkait melakukan pekerjaan dengan baik.
Catatan Samping
Sedikit keluar dari topik, tapi hati-hati menggunakan semua jenis "pemblokiran" pada utas GUI WinForms karena itu ditandai dengan [STAThread]
. Penggunaan await
tidak akan memblokir sama sekali, tetapi terkadang saya melihatnya digunakan sehubungan dengan semacam pemblokiran.
"Blokir" ada dalam tanda kutip karena Anda secara teknis tidak dapat memblokir utas GUI WinForms . Ya, jika Anda menggunakan lock
pada utas GUI WinForms, ia masih akan memompa pesan, meskipun Anda mengira itu "diblokir". Ini bukan.
Ini dapat menyebabkan masalah aneh dalam kasus yang sangat jarang terjadi. Salah satu alasan Anda tidak ingin menggunakan lock
saat melukis, misalnya. Tapi itu kasus pinggiran dan kompleks; Namun saya telah melihatnya menyebabkan masalah gila. Jadi saya mencatatnya demi kelengkapan.