根据您的问题...
如何在C#中将参数传递给Thread.ThreadStart()方法?
...以及您遇到的错误,您必须从以下位置更正代码
Thread thread = new Thread(new ThreadStart(download(filename));
至
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
但是,这个问题乍看起来似乎更加复杂。
Thread
当前的类(4.7.2)提供了几个构造函数和一个Start
带有重载的方法。
这些相关的构造函数是:
public Thread(ThreadStart start);
和
public Thread(ParameterizedThreadStart start);
可以选择一个ThreadStart
代表或一个ParameterizedThreadStart
代表。
相应的代表如下所示:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
可以看出,要使用的正确构造函数似乎是接受ParameterizedThreadStart
委托的构造函数,以便某些方法可以由线程启动符合委托的指定签名的方法。
初始化Thread
类的一个简单示例是
Thread thread = new Thread(new ParameterizedThreadStart(Work));
要不就
Thread thread = new Thread(Work);
相应方法的签名(Work
在此示例中称为)如下所示:
private void Work(object data)
{
...
}
剩下的就是启动线程。这可以通过使用以下任一方法来完成
public void Start();
要么
public void Start(object parameter);
虽然Start()
将启动线程并将其null
作为数据传递给方法,但是Start(...)
可以将任何东西传递Work
给线程的方法。
但是,这种方法存在一个大问题:传递给该Work
方法的所有内容都被转换为对象。这意味着必须在Work
方法内将其再次强制转换为原始类型,如以下示例所示:
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}");
}
强制转换是您通常不希望执行的操作。
如果有人传递了不是字符串的其他东西怎么办?乍看起来似乎是不可能的(因为这是我的方法,因为我知道我在做什么,或者该方法是私有的,所以有人应该如何将任何东西传递给它?),由于各种原因,您可能最终会遇到这种情况。由于某些情况可能不是问题,其他情况则是。在这种情况下InvalidCastException
,您可能会得到一个可能根本不会注意到的,因为它只是终止了线程。
作为一种解决方案,您希望获得一个通用ParameterizedThreadStart
委托,例如要传递到方法中的数据类型ParameterizedThreadStart<T>
在哪里。不幸的是,这样的东西不存在(还?)。T
Work
但是,有针对此问题的建议解决方案。它涉及创建一个类,该类既包含要传递给线程的数据,又包含表示worker方法的方法,如下所示:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
使用这种方法,您将像这样启动线程:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
因此,以这种方式,您只需避免进行转换,并拥有一种将数据提供给线程的类型安全方式;-)