Theo câu hỏi của bạn ...
Làm cách nào để truyền tham số cho phương thức Thread.ThreadStart () trong C #?
... và lỗi bạn gặp phải, bạn sẽ phải sửa mã của mình từ
Thread thread = new Thread(new ThreadStart(download(filename));
đến
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Tuy nhiên, câu hỏi phức tạp hơn lúc đầu.
Các Thread
lớp học hiện nay (4.7.2) cung cấp một số nhà xây dựng và một Start
phương pháp với quá tải.
Những nhà xây dựng có liên quan cho câu hỏi này là:
public Thread(ThreadStart start);
và
public Thread(ParameterizedThreadStart start);
trong đó có một ThreadStart
đại biểu hoặc một ParameterizedThreadStart
đại biểu.
Các đại biểu tương ứng trông như thế này:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Vì vậy, như có thể thấy, các nhà xây dựng chính xác để sử dụng dường như là một trong những ParameterizedThreadStart
đại biểu để một số phương thức phù hợp với chữ ký được chỉ định của đại biểu có thể được bắt đầu bởi luồng.
Một ví dụ đơn giản để kích hoạt Thread
lớp học sẽ là
Thread thread = new Thread(new ParameterizedThreadStart(Work));
hoặc chỉ
Thread thread = new Thread(Work);
Chữ ký của phương thức tương ứng (được gọi Work
trong ví dụ này) trông như thế này:
private void Work(object data)
{
...
}
Những gì còn lại là bắt đầu chuỗi. Điều này được thực hiện bằng cách sử dụng một trong hai
public void Start();
hoặc là
public void Start(object parameter);
Trong khi Start()
sẽ bắt đầu luồng và truyền null
dưới dạng dữ liệu cho phương thức, Start(...)
có thể được sử dụng để truyền bất cứ thứ gì vào Work
phương thức của luồng.
Tuy nhiên, có một vấn đề lớn với cách tiếp cận này: Mọi thứ được truyền vào Work
phương thức đều được đưa vào một đối tượng. Điều đó có nghĩa là trong Work
phương thức nó phải được chuyển sang loại ban đầu như trong ví dụ sau:
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}");
}
Đúc là điều bạn thường không muốn làm.
Điều gì xảy ra nếu ai đó vượt qua một thứ khác không phải là một chuỗi? Vì điều này ban đầu dường như không thể (vì đó là phương pháp của tôi, tôi biết tôi làm gì hoặc Phương pháp này là riêng tư, làm thế nào để ai đó có thể chuyển bất cứ điều gì cho nó? ) Bạn có thể kết thúc chính xác với trường hợp đó vì nhiều lý do . Vì một số trường hợp có thể không phải là một vấn đề, những người khác là. Trong những trường hợp như vậy, bạn có thể sẽ kết thúc với mộtInvalidCastException
cái mà bạn có thể sẽ không nhận thấy bởi vì nó chỉ đơn giản là chấm dứt chuỗi.
Là một giải pháp bạn mong đợi để có được một ParameterizedThreadStart
đại biểu chung như ParameterizedThreadStart<T>
nơi T
sẽ là loại dữ liệu bạn muốn truyền vàoWork
phương thức. Thật không may, một cái gì đó như thế này không tồn tại (chưa?).
Tuy nhiên, có một giải pháp được đề xuất cho vấn đề này. Nó liên quan đến việc tạo một lớp chứa cả hai, dữ liệu được truyền đến luồng cũng như phương thức đại diện cho phương thức worker như thế này:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Với phương pháp này, bạn sẽ bắt đầu chuỗi như thế này:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Vì vậy, theo cách này, bạn chỉ cần tránh truyền xung quanh và có một cách an toàn để cung cấp dữ liệu cho một chuỗi ;-)