首页 文章

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

提问于
浏览
256

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

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

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

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

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

期望的错误方法类型 .

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

9 回答

  • 628

    最简单的就是

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

    这个(超过 ParameterizedThreadStart )的优点是你可以传递多个参数,并且你可以获得编译时检查,而无需始终从 object 进行强制转换 .

  • -1

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

    用法示例:

    var thread = new Thread(new ParameterizedThreadStart(download));
    //var thread = new Thread(download); // equivalent
    
    thread.Start(filename)
    
  • 1

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

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

    看看这个例子:

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

    但是你的'download'方法仍然需要 object ,而不是 string 作为参数 . 您可以将其强制转换为方法体中的字符串 .

  • 31

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

    另外的

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

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

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

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

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

    根据你的问题......

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

    ...以及您遇到的错误,您必须更正您的代码

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

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

    However, the question is more complex as it seems at first.

    当前的Thread类(4.7.2)提供了多个带有重载的constructorsStart方法 .

    这个问题的相关构造函数是:

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

    Casting is something you typically do not want to do.

    如果有人传递了不是字符串的其他内容怎么办?因为这在一开始似乎是不可能的(因为这是我的方法,我知道我做了什么或者方法是私有的,怎么应该有人能够传递任何东西?)你可能因为各种原因而最终得到这种情况 . 由于某些情况可能不是问题,其他情况也是如此 . 在这种情况下,您可能会得到InvalidCastException,您可能不会注意到它,因为它只是终止了线程 .

    作为一种解决方案,您可以获得一个通用的 ParameterizedThreadStart 委托,如 ParameterizedThreadStart<T> ,其中 T 将是您要传递给 Work 方法的数据类型 . 不幸的是,这样的事情不存在(但是?) .

    然而,这个问题有一个suggested solution . 它涉及创建一个包含两者的类,要传递给线程的数据以及表示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();
    

    因此,通过这种方式,您可以简单地避免转换,并提供一种向线程提供数据的类型安全方式;-)

相关问题