如何在c#中使用参数启动线程?


当前回答

正如在这里的各种回答中已经提到的,Thread类目前(4.7.2)提供了几个构造函数和一个带有重载的Start方法。

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

public Thread(ThreadStart start);

and

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

or

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. What if someone passes something else which is not a string? As this seems not possible at first (because It is my method, I know what I do or The method is private, how should someone ever be able to pass anything to it?) you may possibly end up with exactly that case for various reasons. As some cases may not be a problem, others are. In such cases you will probably end up with an InvalidCastException which you probably will not notice because it simply terminates the thread.

作为一种解决方案,您可能希望获得一个通用的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();

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

其他回答

是的:

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);

Thread构造函数的两个重载之一采用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) {
  ...
}

使用lambda表达式的一种非常简单和方便的方式是这样的:

Thread thread = new Thread( (param) => {
    string name = param as string;
    // rest of code goes here.
});
thread.Start("MyName");

通过这种方式,lambda表达式可以具有参数并在单独的线程中运行内联代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {

            int x = 10;
            Thread t1 =new Thread(new ParameterizedThreadStart(order1));
            t1.IsBackground = true;//i can stope 
            t1.Start(x);

            Thread t2=new Thread(order2);
            t2.Priority = ThreadPriority.Highest;
            t2.Start();

            Console.ReadKey();
        }//Main

        static void  order1(object args)
        {
            int x = (int)args;


                for (int i = 0; i < x; i++)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write(i.ToString() + " ");
            }
        }

        static void order2()
        {
            for (int i = 100; i > 0; i--)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write(i.ToString() + " ");
            }
        }`enter code here`
    }
}

我在传递参数时有问题。 我将一个整数从for循环传递给函数并显示它,但它总是给出不同的结果。例如(1,2,2,3)(1,2,3,3)(1,1,2,3)等与paramtrizedthreadstart委托。

这个简单的代码很有魔力

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

private void Work(object param) 
{
 string Parameter = (string)param; 
}