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 Threadkelas saat (4.7.2) menyediakan beberapa konstruktor dan Startmetode dengan overloads.
Konstruktor yang relevan untuk pertanyaan ini adalah:
public Thread(ThreadStart start);
dan
public Thread(ParameterizedThreadStart start);
baik yang mengambil ThreadStartdelegasi atau ParameterizedThreadStartdelegasi.
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 ParameterizedThreadStartdelegasi sehingga beberapa metode sesuai dengan tanda tangan yang ditentukan dari delegasi dapat dimulai oleh utas.
Contoh sederhana untuk instanciating Threadkelas akan menjadi
Thread thread = new Thread(new ParameterizedThreadStart(Work));
atau hanya
Thread thread = new Thread(Work);
Tanda tangan dari metode yang sesuai (disebut Workdalam 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 nullsebagai data ke metode, Start(...)dapat digunakan untuk melewatkan apa pun ke dalam Workmetode utas.
Namun ada satu masalah besar dengan pendekatan ini: Segala sesuatu yang dilewatkan ke dalam Workmetode dilemparkan ke objek. Itu berarti dalam Workmetode 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 InvalidCastExceptionyang mungkin tidak akan Anda perhatikan karena itu hanya mengakhiri utas.
Sebagai solusi Anda akan mengharapkan untuk mendapatkan ParameterizedThreadStartdelegasi generik seperti di ParameterizedThreadStart<T>mana Takan menjadi tipe data yang ingin Anda sampaikan ke dalam Workmetode. 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 ;-)