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


是的:

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) {
  ...
}
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"
    }
}

你可以使用一个paramtrizedthreadstart委托:

string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);

ParameterizedThreadStart接受一个参数。您可以使用它来发送一个参数或包含多个属性的自定义类。

另一种方法是将想要启动的方法作为实例成员放在类中,并将其与想要设置的参数的属性放在一起。创建类的实例,设置属性并启动指定实例和方法的线程,这样方法就可以访问属性。

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

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

参数类型必须为对象。

编辑:

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

您可以使用BackgroundWorker RunWorkerAsync方法并传入您的值。

你可以使用lambda表达式

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

这是目前为止我能找到的最好的答案,又快又简单。

我在传递参数时有问题。 我将一个整数从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; 
}

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

Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();

或者你甚至可以像这样使用ThreadStart委托…

private void DoSomething(int param1, string param2)
{
    //DO SOMETHING...
    ThreadStart ts = delegate
    {
        if (param1 > 0) DoSomethingElse(param2, "param3");
    };   
    new Thread(ts).Start();
    //DO SOMETHING...
}

或者使用。net 4.5+甚至更干净,像这样..

private void DoSomething(int param1, string param2)
{
    //DO SOMETHING..
    void ts()
    {
        if (param1 > 0) DoSomethingElse(param2, "param3");
    }
    new Thread(ts).Start();
    //DO SOMETHING..
}
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.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() + " ");
            }
        }
    }
}
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`
    }
}

正如在这里的各种回答中已经提到的,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();

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

我建议使用Task<T>而不是Thread;它允许多个参数并且执行得非常好。

下面是一个工作示例:

    public static void Main()
    {
        List<Task> tasks = new List<Task>();

        Console.WriteLine("Awaiting threads to finished...");

        string par1 = "foo";
        string par2 = "boo";
        int par3 = 3;

        for (int i = 0; i < 1000; i++)
        {
            tasks.Add(Task.Run(() => Calculate(par1, par2, par3))); 
        }

        Task.WaitAll(tasks.ToArray());

        Console.WriteLine("All threads finished!");
    }

    static bool Calculate1(string par1, string par2, int par3)
    {
        lock(_locker)
        {
            //...
            return true;
        }
    }

    // if need to lock, use this:
    private static Object _locker = new Object();"

    static bool Calculate2(string par1, string par2, int par3)
    {
        lock(_locker)
        {
            //...
            return true;
        }
    }

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

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

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