带参数的ThreadStart

JL.*_*JL. 248 c# multithreading

如何使用C#中的参数启动一个线程?

Jar*_*Par 464

Thread构造函数的2个重载之一使用ParameterizedThreadStart委托,它允许您将单个参数传递给start方法.不幸的是,虽然它只允许一个参数,但它以不安全的方式这样做,因为它将它作为对象传递.我发现使用lambda表达式捕获相关参数并以强类型方式传递它们要容易得多.

请尝试以下方法

public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
  var t = new Thread(() => RealStart(param1, param2));
  t.Start();
  return t;
}

private static void RealStart(SomeType param1, SomeOtherType param2) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

  • +1:尽管当前选择的答案是绝对正确的,但JaredPar的这个答案更好.它对大多数实际案例来说都是最好的解决方案. (38认同)
  • 太棒了,这是针对VB.NET的人`Dim thr As New Thread(Sub()DoStuff(设置))` (12认同)
  • 很好很简单.只需在"new Thread(()=> FooBar())中包装任何调用.Start(); (5认同)
  • @bavaza我只是指静态类型检查 (3认同)
  • 这个解决方案比标准的ParameterizedThreadStart更好 (2认同)

Eri*_*ick 165

是的:

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
Run Code Online (Sandbox Code Playgroud)

  • 什么是myParamObject和myUrl? (42认同)
  • 是这样的:ThreadStart processTaskThread = delegate {ProcessTasks(databox.DataboxID); }; new Thread(processTaskThread).Start(); (13认同)
  • -1因为答案假定OP知道如何使用`ParameterizedThreadStart`并且从问题文本中清楚地知道,情况可能并非如此. (10认同)
  • 在这种情况下,`void MyParamObject(object myUrl){// do stuff}`应该有参数类型`object` (3认同)
  • 我有这个错误错误 CS0123 'UpdateDB' 没有重载匹配委托 'ParameterizedThreadStart' (3认同)

Geo*_*-it 126

您可以使用lambda表达式

private void MyMethod(string param1,int param2)
{
  //do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是我能找到的最好的答案,它快速而简单.

  • IMO简单案例的最佳解决方案 (4认同)
  • 这是一个lambda表达式,可以在这些地址上找到一些信息:msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx | http://www.codeproject.com/Articles/24255/Exploring-Lambda-Expression-in-C | http://www.dotnetperls.com/lambda (2认同)

Spe*_*ort 34

Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param)
{
    string Parameter = (string)param;
}
Run Code Online (Sandbox Code Playgroud)

参数类型必须是对象.

编辑:

虽然这个答案并不正确,但我建议不要采用这种方法.使用lambda表达式更容易阅读,不需要类型转换.请参见:https://stackoverflow.com/a/1195915/52551

  • 我发现这比接受的答案更清晰. (6认同)

hus*_*int 29

class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));

        t.Start("My Parameter");
    }

    static void ThreadMethod(object parameter)
    {
        // parameter equals to "My Parameter"
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这让我"没有超载'DoWork'匹配委托'System.Threading.ParameterizedThreadStart' (3认同)

Mas*_*ick 24

使用lambda的简单方法就是这样..

Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
Run Code Online (Sandbox Code Playgroud)

或者你甚至可以这样delegate使用ThreadStart......

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


Jus*_*ner 8

使用ParameterizedThreadStart.

  • 这太可怕了:) (12认同)

Mar*_*far 8

正如这里的各种答案中已经提到的那样,Thread该类当前(4.7.2)提供了几个构造函数和一个Start具有重载的方法。

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

public Thread(ThreadStart start);
Run Code Online (Sandbox Code Playgroud)

public Thread(ParameterizedThreadStart start);
Run Code Online (Sandbox Code Playgroud)

要么接受ThreadStart委托要么接受ParameterizedThreadStart委托。

相应的代表如下所示:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Run Code Online (Sandbox Code Playgroud)

因此可以看出,使用的正确构造函数似乎是接受ParameterizedThreadStart委托的构造函数,以便线程可以启动符合委托指定签名的某些方法。

实例化Thread类的一个简单示例是

Thread thread = new Thread(new ParameterizedThreadStart(Work));
Run Code Online (Sandbox Code Playgroud)

要不就

Thread thread = new Thread(Work);
Run Code Online (Sandbox Code Playgroud)

相应方法(Work在本例中调用)的签名如下所示:

private void Work(object data)
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

剩下的就是启动线程。这是通过使用

public void Start();
Run Code Online (Sandbox Code Playgroud)

或者

public void Start(object parameter);
Run Code Online (Sandbox Code Playgroud)

WhileStart()将启动线程并将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}");
}
Run Code Online (Sandbox Code Playgroud)



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

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

作为解决方案,你会期望得到一个通用的ParameterizedThreadStart委托像ParameterizedThreadStart<T>这里T将要传递到数据的类型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}");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);

thread.Start();
Run Code Online (Sandbox Code Playgroud)

因此,通过这种方式,您只需避免强制转换并使用类型安全的方式向线程提供数据;-)


小智 5

我在传递的参数中遇到了问题.我将for循环中的整数传递给函数并显示它,但它总是给出不同的结果.喜欢(1,2,2,3)(1,2,3,3)(1,1,2,3)等与 ParametrizedThreadStart委托.

这个简单的代码充当了魅力

Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param) 
{
 string Parameter = (string)param; 
}
Run Code Online (Sandbox Code Playgroud)