Sorunuza göre ...
Parametreleri C # 'da Thread.ThreadStart () yöntemine geçirmek nasıl?
... ve karşılaştığınız hatayı, kodunuzu
Thread thread = new Thread(new ThreadStart(download(filename));
için
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Ancak, soru ilk bakışta göründüğü gibi daha karmaşıktır.
ThreadSınıfı şu anda (4.7.2) birçok içerir kurucular ve Startaşırı yük yöntemi.
Bu soru için bu ilgili kurucular:
public Thread(ThreadStart start);
ve
public Thread(ParameterizedThreadStart start);
ya bir ThreadStartdelege ya da bir ParameterizedThreadStartdelege alır.
Karşılık gelen delegeler şöyle görünür:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Görülebileceği gibi, kullanılacak doğru kurucu bir ParameterizedThreadStarttemsilci alan kişi gibi görünmektedir, böylece temsilci tarafından belirtilen imzayla uyumlu bazı yöntemler iş parçacığı tarafından başlatılabilir.
ThreadSınıfı örneklemek için basit bir örnek
Thread thread = new Thread(new ParameterizedThreadStart(Work));
ya da sadece
Thread thread = new Thread(Work);
İlgili yöntemin imzası ( Workbu örnekte denir ) şöyle görünür:
private void Work(object data)
{
...
}
Geriye kalan, iş parçacığını başlatmaktır. Bu, aşağıdakilerden birini kullanarak yapılır:
public void Start();
veya
public void Start(object parameter);
İken Start()açtığınızda, gerekli geçerdi nullyönteme veri olarak, Start(...)geçmek kullanılabilir şey içine Workiplik yöntemi.
Ancak bu yaklaşımda büyük bir sorun var: WorkYönteme aktarılan her şey bir nesneye dökülüyor. Bu, Workyöntem içinde, aşağıdaki örnekte olduğu gibi tekrar orijinal türe çevrilmesi gerektiği anlamına gelir :
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}");
}
Döküm genellikle yapmak istemediğiniz bir şeydir.
Birisi dize olmayan başka bir şey geçerse ne olur? Bu ilk başta mümkün görünmediği için (çünkü bu benim yöntemim, ne yaptığımı biliyorum veya yöntem özel, birisi ona herhangi bir şeyi nasıl geçebilir? ) Muhtemelen çeşitli nedenlerden dolayı tam olarak bu dava ile sonuçlanabilir . Bazı vakalar sorun yaratmayabileceğinden diğerleri. Bu gibi durumlarda, muhtemelen InvalidCastExceptioniş parçacığını sonlandırdığı için muhtemelen fark etmeyeceğiniz bir sonuç alırsınız.
Bir çözüm olarak bir jenerik olsun beklenir ParameterizedThreadStartgibi temsilci ParameterizedThreadStart<T>nereye Tsen geçirmek istediğiniz türde veriler olacağını Workyöntemle. Ne yazık ki böyle bir şey henüz yok (henüz?).
Ancak , bu soruna önerilen bir çözüm vardır . İş parçacığına iletilecek verileri ve bunun gibi işçi yöntemini temsil eden yöntemi içeren bir sınıf oluşturmayı içerir:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Bu yaklaşımla iş parçacığını şöyle başlatacaksınız:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Böylece bu şekilde döküm yapmaktan kaçınır ve bir iş parçacığına veri sağlamanın tipik bir yoluna sahip olursunuz ;-)