Bagaimana Anda memulai utas dengan parameter dalam C #?
c#
multithreading
JL.
sumber
sumber
Jawaban:
Yap:
sumber
void MyParamObject(object myUrl){ //do stuff }
harus memiliki tipe parameterobject
ParameterizedThreadStart
dan dengan jelas dari teks pertanyaan, yang mungkin bukan itu masalahnya.Salah satu dari 2 kelebihan konstruktor Thread mengambil delegasi ParameterizedThreadStart yang memungkinkan Anda untuk melewatkan parameter tunggal ke metode mulai. Sayangnya meskipun hanya memungkinkan untuk satu parameter dan melakukannya dengan cara yang tidak aman karena dilewatkan sebagai objek. Saya menemukan jauh lebih mudah untuk menggunakan ekspresi lambda untuk menangkap parameter yang relevan dan meneruskannya dengan cara yang sangat diketik.
Coba yang berikut ini
sumber
Dim thr As New Thread(Sub() DoStuff(settings))
Anda dapat menggunakan ekspresi lambda
sejauh ini jawaban terbaik yang bisa saya temukan, cepat dan mudah.
sumber
Tipe parameter harus berupa objek.
EDIT:
Meskipun jawaban ini tidak salah, saya merekomendasikan pendekatan ini. Menggunakan ekspresi lambda jauh lebih mudah dibaca dan tidak memerlukan casting tipe. Lihat di sini: https://stackoverflow.com/a/1195915/52551
sumber
Parameter
?sumber
Cara sederhana menggunakan lambda seperti itu ..
ATAU Anda bahkan dapat
delegate
menggunakanThreadStart
seperti ...ATAU menggunakan VS 2019. NET 4.5+ lebih bersih seperti itu ..
sumber
Gunakan
ParametrizedThreadStart
.sumber
Gunakan ParameterizedThreadStart .
sumber
Seperti telah disebutkan dalam berbagai jawaban di sini,
Thread
kelas saat ini (4.7.2) menyediakan beberapa konstruktor danStart
metode dengan kelebihan.Konstruktor yang relevan untuk pertanyaan ini adalah:
dan
baik yang mengambil
ThreadStart
delegasi atauParameterizedThreadStart
delegasi.Delegasi yang sesuai terlihat seperti ini:
Jadi seperti yang dapat dilihat, konstruktor yang benar untuk digunakan tampaknya adalah orang yang mengambil
ParameterizedThreadStart
delegasi sehingga beberapa metode sesuai dengan tanda tangan yang ditentukan dari delegasi dapat dimulai oleh utas.Contoh sederhana untuk instanciating
Thread
kelas akan menjadiatau hanya
Tanda tangan dari metode yang sesuai (disebut
Work
dalam contoh ini) terlihat seperti ini:Yang tersisa adalah memulai utas. Ini dilakukan dengan menggunakan keduanya
atau
Sementara
Start()
akan memulai utas dan meneruskannull
sebagai data ke metode,Start(...)
dapat digunakan untuk melewatkan apa pun ke dalamWork
metode utas.Namun ada satu masalah besar dengan pendekatan ini: Segala sesuatu yang dilewatkan ke dalam
Work
metode dilemparkan ke objek. Itu berarti dalamWork
metode itu harus dilemparkan ke tipe asli lagi seperti pada contoh berikut:Casting adalah sesuatu yang biasanya tidak ingin Anda lakukan.
Bagaimana jika seseorang melewati sesuatu yang bukan string? Karena ini kelihatannya tidak mungkin pada awalnya (karena ini adalah metode saya, saya tahu apa yang saya lakukan atau metode ini bersifat pribadi, bagaimana mungkin seseorang bisa memberikan sesuatu padanya? ) Anda mungkin berakhir dengan kasus seperti itu karena berbagai alasan . Karena beberapa kasus mungkin tidak menjadi masalah, yang lain juga. Dalam kasus seperti itu Anda mungkin akan berakhir dengan
InvalidCastException
yang Anda mungkin tidak akan perhatikan karena itu hanya mengakhiri utas.Sebagai solusi Anda akan mengharapkan untuk mendapatkan
ParameterizedThreadStart
delegasi generik seperti diParameterizedThreadStart<T>
manaT
akan menjadi tipe data yang ingin Anda sampaikan ke dalamWork
metode. Sayangnya sesuatu seperti ini belum ada (belum?).Namun ada solusi yang disarankan untuk masalah ini. Ini melibatkan pembuatan kelas yang berisi keduanya, data yang akan diteruskan ke utas serta metode yang mewakili metode pekerja seperti ini:
Dengan pendekatan ini Anda akan memulai utas seperti ini:
Jadi dengan cara ini Anda cukup menghindari casting dan memiliki cara yang aman untuk memberikan data ke utas ;-)
sumber
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
tidak mungkin dan sebagainya)if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
. Bagaimanapun, alih-alih menggunakan metode threading Anda, saya menemukan sedikit lebih nyaman untuk digunakanTasks<T>
, seperti misalnyatasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
, lihat jawaban saya di bawah ( stackoverflow.com/a/59777250/7586301 )Saya mengalami masalah pada parameter yang diteruskan. Saya melewati bilangan bulat dari for loop ke fungsi dan menampilkannya, tetapi selalu memberikan hasil yang berbeda. seperti (1,2,2,3) (1,2,3,3) (1,1,2,3) dll dengan delegasi ParametrizedThreadStart .
kode sederhana ini berfungsi sebagai pesona
sumber
Itu
ParameterizedThreadStart
mengambil satu parameter. Anda dapat menggunakannya untuk mengirim satu parameter, atau kelas khusus yang berisi beberapa properti.Metode lain adalah dengan meletakkan metode yang ingin Anda mulai sebagai anggota instance di kelas bersama dengan properti untuk parameter yang ingin Anda atur. Buat instance dari kelas, atur properti dan mulai utas yang menentukan instance dan metode, dan metode ini dapat mengakses properti.
sumber
Anda bisa menggunakan delegasi ParametrizedThreadStart :
sumber
Anda dapat menggunakan metode BackgroundWorker RunWorkerAsync dan memberikan nilai Anda.
sumber
sumber
Saya mengusulkan menggunakan
Task<T>
bukanThread
; itu memungkinkan beberapa parameter dan menjalankan sangat baik.Berikut ini contoh kerjanya:
sumber
sumber