如何将参数传递给Thread.ThreadStart()C#中的方法?
假设我有一个名为“下载”的方法
public void download(string filename)
{
// download code
}
现在,我在main方法中创建了一个线程:
Thread thread = new Thread(new ThreadStart(download(filename));
错误方法类型预期。
如何将参数传递给ThreadStart带有参数的目标方法?
如何将参数传递给Thread.ThreadStart()C#中的方法?
假设我有一个名为“下载”的方法
public void download(string filename)
{
// download code
}
现在,我在main方法中创建了一个线程:
Thread thread = new Thread(new ThreadStart(download(filename));
错误方法类型预期。
如何将参数传递给ThreadStart带有参数的目标方法?
Answers:
最简单的就是
string filename = ...
Thread thread = new Thread(() => download(filename));
thread.Start();
(相对于ParameterizedThreadStart)的优点是,您可以传递多个参数,并且无需进行object所有转换就可以进行编译时检查。
new Thread(delegate() { download(filename); });
看这个例子:
public void RunWorker()
{
Thread newThread = new Thread(WorkerMethod);
newThread.Start(new Parameter());
}
public void WorkerMethod(object parameterObj)
{
var parameter = (Parameter)parameterObj;
// do your job!
}
首先通过将委托传递给worker方法来创建线程,然后使用Thread.Start方法启动该线程,该方法将您的对象作为参数。
因此,在您的情况下,您应该像这样使用它:
Thread thread = new Thread(download);
thread.Start(filename);
但是您的“下载”方法仍然需要使用object而不是string作为参数。您可以将其转换为方法主体中的字符串。
您要对使用ParameterizedThreadStart参数的线程方法使用委托。(或者实际上什么也没有,让Thread构造函数进行推断。)
用法示例:
var thread = new Thread(new ParameterizedThreadStart(download));
//var thread = new Thread(download); // equivalent
thread.Start(filename)
另外的
Thread thread = new Thread(delegate() { download(i); });
thread.Start();
您可以将线程函数(下载)和所需的参数(文件名)封装在一个类中,并使用ThreadStart委托执行线程函数。
public class Download
{
string _filename;
Download(string filename)
{
_filename = filename;
}
public void download(string filename)
{
//download code
}
}
Download = new Download(filename);
Thread thread = new Thread(new ThreadStart(Download.download);
我建议您再开设一个名为File的课程。
public class File
{
private string filename;
public File(string filename)
{
this.filename= filename;
}
public void download()
{
// download code using filename
}
}
在线程创建代码中,实例化一个新文件:
string filename = "my_file_name";
myFile = new File(filename);
ThreadStart threadDelegate = new ThreadStart(myFile.download);
Thread newThread = new Thread(threadDelegate);
这样如何:(或者可以这样使用吗?)
var test = "Hello";
new Thread(new ThreadStart(() =>
{
try
{
//Staff to do
Console.WriteLine(test);
}
catch (Exception ex)
{
throw;
}
})).Start();
根据您的问题...
如何在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>在哪里。不幸的是,这样的东西不存在(还?)。TWork
但是,有针对此问题的建议解决方案。它涉及创建一个类,该类既包含要传递给线程的数据,又包含表示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();
因此,以这种方式,您只需避免进行转换,并拥有一种将数据提供给线程的类型安全方式;-)
这是完美的方式...
private void func_trd(String sender)
{
try
{
imgh.LoadImages_R_Randomiz(this, "01", groupBox, randomizerB.Value); // normal code
ThreadStart ts = delegate
{
ExecuteInForeground(sender);
};
Thread nt = new Thread(ts);
nt.IsBackground = true;
nt.Start();
}
catch (Exception)
{
}
}
private void ExecuteInForeground(string name)
{
//whatever ur function
MessageBox.Show(name);
}