Menurut pertanyaan Anda ...
Bagaimana cara mengirimkan parameter ke metode Thread.ThreadStart () di C #?
... dan kesalahan yang Anda temui, Anda harus memperbaiki kode Anda dari
Thread thread = new Thread(new ThreadStart(download(filename));
untuk
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Namun, pertanyaannya lebih kompleks seperti pada awalnya.
The Thread
kelas saat (4.7.2) menyediakan beberapa konstruktor dan Start
metode dengan overloads.
Konstruktor yang relevan untuk pertanyaan ini adalah:
public Thread(ThreadStart start);
dan
public Thread(ParameterizedThreadStart start);
baik yang mengambil ThreadStart
delegasi atau ParameterizedThreadStart
delegasi.
Delegasi yang sesuai terlihat seperti ini:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Jadi seperti yang bisa dilihat, konstruktor yang tepat 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 menjadi
Thread thread = new Thread(new ParameterizedThreadStart(Work));
atau hanya
Thread thread = new Thread(Work);
Tanda tangan dari metode yang sesuai (disebut Work
dalam contoh ini) terlihat seperti ini:
private void Work(object data)
{
...
}
Yang tersisa adalah memulai utas. Ini dilakukan dengan menggunakan keduanya
public void Start();
atau
public void Start(object parameter);
Sementara Start()
akan memulai utas dan meneruskan null
sebagai data ke metode, Start(...)
dapat digunakan untuk melewatkan apa pun ke dalam Work
metode utas.
Namun ada satu masalah besar dengan pendekatan ini: Segala sesuatu yang dilewatkan ke dalam Work
metode dilemparkan ke objek. Itu berarti dalam Work
metode itu harus dilemparkan ke tipe asli lagi seperti pada contoh berikut:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
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 apa pun 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 sesuatu InvalidCastException
yang mungkin tidak akan Anda perhatikan karena itu hanya mengakhiri utas.
Sebagai solusi Anda akan mengharapkan untuk mendapatkan ParameterizedThreadStart
delegasi generik seperti di ParameterizedThreadStart<T>
mana T
akan menjadi tipe data yang ingin Anda sampaikan ke dalam Work
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:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Dengan pendekatan ini Anda akan memulai utas seperti ini:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Jadi dengan cara ini Anda cukup menghindari casting dan memiliki cara yang aman untuk memberikan data ke utas ;-)