带参数的ThreadStart

时间:2009-07-28 18:31:36

标签: c# multithreading

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

17 个答案:

答案 0 :(得分:441)

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

答案 1 :(得分:155)

是的:

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

答案 2 :(得分:118)

您可以使用lambda表达式

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

这是迄今为止我能找到的最佳答案,它快速而简单。

答案 3 :(得分:34)

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

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

参数类型必须是对象。

修改

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

答案 4 :(得分: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"
    }
}

答案 5 :(得分:23)

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

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

您甚至delegate使用ThreadStart就可以......

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

答案 6 :(得分:7)

答案 7 :(得分:7)

答案 8 :(得分: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; 
}

答案 9 :(得分:4)

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

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

答案 10 :(得分:3)

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

答案 11 :(得分:3)

您可以使用ParametrizedThreadStart代理:

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

答案 12 :(得分:1)

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`
    }
}

答案 13 :(得分:0)

我建议使用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;
        }
    }

答案 14 :(得分:0)

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

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

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

答案 15 :(得分:-1)

正如在这里的各种答案中已经提到的那样,当前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}");
    }
}

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

答案 16 :(得分:-2)

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