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.
Thread
Sınıfı şu anda (4.7.2) birçok içerir kurucular ve Start
aşırı yük yöntemi.
Bu soru için bu ilgili kurucular:
public Thread(ThreadStart start);
ve
public Thread(ParameterizedThreadStart start);
ya bir ThreadStart
delege ya da bir ParameterizedThreadStart
delege 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 ParameterizedThreadStart
temsilci 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.
Thread
Sı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ı ( Work
bu ö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 null
yönteme veri olarak, Start(...)
geçmek kullanılabilir şey içine Work
iplik yöntemi.
Ancak bu yaklaşımda büyük bir sorun var: Work
Yönteme aktarılan her şey bir nesneye dökülüyor. Bu, Work
yö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 InvalidCastException
iş 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 ParameterizedThreadStart
gibi temsilci ParameterizedThreadStart<T>
nereye T
sen geçirmek istediğiniz türde veriler olacağını Work
yö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 ;-)