如何将参数传递给Thread中的ThreadStart方法?

时间:2010-07-29 08:15:12

标签: c# .net multithreading

如何在C#中将参数传递给Thread.ThreadStart()方法?

假设我有一个名为'download'的方法

public void download(string filename)
{
    // download code
}

现在我在main方法中创建了一个线程:

Thread thread = new Thread(new ThreadStart(download(filename));
  

预期的错误方法类型。

如何使用带参数的目标方法将参数传递给ThreadStart

10 个答案:

答案 0 :(得分:654)

最简单的只是

string filename = ...
Thread thread = new Thread(() => download(filename));
thread.Start();

这个(超过ParameterizedThreadStart)的优点是您可以传递多个参数,并且无需始终从object进行编译,您可以进行编译时检查。

答案 1 :(得分:33)

看看这个例子:

public void RunWorker()
{
    Thread newThread = new Thread(WorkerMethod);
    newThread.Start(ParameterObject);
}

public void WorkerMethod(object parameterObject)
{
    // do your job!
}

您首先通过将委托传递给worker方法创建一个线程,然后使用Thread.Start方法启动它,该方法将您的对象作为参数。

所以在你的情况下你应该像这样使用它:

    Thread thread = new Thread(download);
    thread .Start(filename);

但是,您的“下载”方法仍然需要将对象,而不是字符串作为参数。您可以将它转换为方法体中的字符串。

答案 2 :(得分:21)

您希望将ParameterizedThreadStart委托用于带参数的线程方法。 (或者根本没有,让Thread构造函数推断。)

使用示例:

var thread = new Thread(new ParameterizedThreadStart(download));
//var thread = new Thread(download); // equivalent

thread.Start(filename)

答案 3 :(得分:4)

你也可以delegate这样......

ThreadStart ts = delegate
{
      bool moreWork = DoWork("param1", "param2", "param3");
      if (moreWork) 
      {
          DoMoreWork("param1", "param2");
      }
};
new Thread(ts).Start();

答案 4 :(得分:3)

我建议您再开设一个名为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);

答案 5 :(得分:2)

您可以将线程函数(下载)和所需参数(文件名)封装在类中,并使用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);

答案 6 :(得分:1)

另外

    Thread thread = new Thread(delegate() { download(i); });
    thread.Start();

答案 7 :(得分:0)

这个怎么样:(或者可以像这样使用吗?)

var test = "Hello";
new Thread(new ThreadStart(() =>
{
    try
    {
        //Staff to do
        Console.WriteLine(test);
    }
    catch (Exception ex)
    {
        throw;
    }
})).Start();

答案 8 :(得分:0)

根据您的问题...

  

如何在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)提供了多个constructors和一个带有重载的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(...)可用于将任何传递到{{1} }线程的方法。

但是这种方法存在一个大问题: 传递到Work方法中的所有内容都强制转换为对象。这意味着在Work方法中,必须再次将其强制转换为原始类型,如以下示例所示:

Work



铸造通常是您不想做的事情。

如果有人传递了不是字符串的其他东西怎么办?乍看起来似乎是不可能的(因为这是我的方法,我知道我要做什么该方法是私有的,所以有人应该如何向其传递任何内容?)由于各种原因,您可能最终会遇到这种情况。由于某些情况可能不是问题,其他情况则是。在这种情况下,您可能会以InvalidCastException结尾,您可能不会注意到它,因为它只是终止了线程。

作为一种解决方案,您希望获得一个像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}"); } 这样的通用ParameterizedThreadStart委托,其中ParameterizedThreadStart<T>是要传递给T方法的数据类型。不幸的是,还不存在这样的东西。

但是,此问题有suggested solution。它涉及到创建一个类,该类既包含要传递给线程的数据,又包含表示worker方法的方法,如下所示:

Work

使用这种方法,您将像这样启动线程:

public class ThreadWithState
{
    private string message;

    public ThreadWithState(string message)
    {
        this.message = message;
    }

    public void Work()
    {
        Console.WriteLine($"I, the thread write: {this.message}");
    }
}

因此,通过这种方式,您只需避免进行转换,并拥有一种向线程提供数据的类型安全方式;-)

答案 9 :(得分:-1)

这是完美的方式......

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);
}