简体   繁体   中英

How to pass more than one parameter to a C# thread?

How to pass more than one parameter to a C# thread? Any example will be appreciated.

Suppose you have a method:

void A(string a, int b) {}

This should work (.NET 2.0):

ThreadStart starter = delegate { A("word", 10); };
Thread thread = new Thread(starter);

thread.Start();

And the following (shorter) for higher versions:

ThreadStart starter = () => A("word", 10);
Thread thread = new Thread(starter);

//or just...
//Thread thread = new Thread(() => A("word",10));

thread.start()

The solutions tsocks has given might not be good for all situations because it specifies the parameters at the time of the creation of the ThreadStart delegate, instead of at the time of execution. This could lead to errors because the parameters might change before the execution which is probably not what you want. Suppose you need to create several threads in a loop, each with it's own parameters:

void CreateAndRunThreads()
{
    List<ThreadStart> threadStartsList = new List<ThreadStart>();

    //delegate creation
    for (int i = 0; i < 5; i++)
    {
        ThreadStart ts = delegate() { PrintInteger(i); };
        threadStartsList.Add(ts);
    }

    //delegate execution (at this moment i=5 in the previous loop)
    foreach(ThreadStart ts in threadStartsList)
    {
        Thread t = new Thread(ts);
        t.Start();
    }
}
private void PrintInteger(int i)
{
    Debug.WriteLine("The integer value: "+i);
}

The output here is as follows:

The integer value: 5
The thread 0x17f0 has exited with code 0 (0x0).
The integer value: 5
The integer value: 5
The thread 0x10f4 has exited with code 0 (0x0).
The integer value: 5
The thread 0x1488 has exited with code 0 (0x0).
The integer value: 5
The thread 0x684 has exited with code 0 (0x0).

Notice that all delegates printed the value 5, not 0 through 4. This is because the ThreadStart delegates use the variable "i", as it is at the moment of execution, not at the moment of the creation of the delegate. So any change (i++ in the loop) to the parameter after the moment of the creation of the delegate will be reflected in the value of the parameter as the delegate executes.

A solution to this problem is to use ParameterizedThreadStart and a custom class which aggregates all your parameters(if there are more). With parameterizedThreadStart, you pass the parameters at the time of execution. This would look something like this:

    class CustomParameters
{
    public int IntValue { get; set; }
    public string FriendlyMessage { get; set; }
}

private void CreateAndRunThreadsWithParams()
{
    List<ParameterizedThreadStart> threadStartsList = new List<ParameterizedThreadStart>();

    //delegate creation
    for (int i = 0; i < 5; i++)
    {
        ParameterizedThreadStart ts = delegate(object o) { PrintCustomParams((CustomParameters)o); };
        threadStartsList.Add(ts);
    }

    //delegate execution
    for (int i=0;i<threadStartsList.Count;i++)
    {
        Thread t = new Thread(threadStartsList[i]);
        t.Start(new CustomParameters() { IntValue = i, FriendlyMessage = "Hello friend! Your integer value is:{0}"});
    }
}

private void PrintCustomParams(CustomParameters customParameters)
{
    Debug.WriteLine(string.Format(customParameters.FriendlyMessage, customParameters.IntValue));
}

The output is shown here:

    Hello friend! Your integer value is:1
The thread 0x1510 has exited with code 0 (0x0).
Hello friend! Your integer value is:0
The thread 0x13f4 has exited with code 0 (0x0).
Hello friend! Your integer value is:2
The thread 0x157c has exited with code 0 (0x0).
Hello friend! Your integer value is:3
The thread 0x14e4 has exited with code 0 (0x0).
Hello friend! Your integer value is:4
The thread 0x1738 has exited with code 0 (0x0).

(The order of execution is not deterministic, it's a race between the threads)

For C# 3.0 you can avoid the ugly object array passing with anonymous methods:

void Run()
{
    string param1 = "hello";
    int param2 = 42;

    Thread thread = new Thread(delegate()
    {
        MyMethod(param1,param2);
    });
    thread.Start();
}

void MyMethod(string p,int i)
{

}

one of the simplest way to pass parameter to thread as

Thread xmlThread =new Thread( ()=>WriteLog(LogTypes.Message, "Flag", "Module", "Location", "Text", "Stacktrace"));
                xmlThread.Start();



private object WriteLog(LogTypes logTypes, string p, string p_2, string p_3, string p_4, string p_5)
        {

        }
public void Start()
        {
            var t1 = new Thread((message) => { Console.WriteLine(message); });
            //the parametirized threadstart accepts objects, it is not generic
            var t2 = new Thread(number => { var num = (int)number;
            Console.WriteLine(num++);
            });
            var t3 = new Thread((vals)=> work(vals));

            t1.Start();
            t2.Start();
            t3.Start(20);
        }

        public void work(params object[] vals)
        {

        }

You can use an array to set parameter with multiple values....

 class Program
{
    public static void Method1(object param)
    {
        object[] parameters = (object[])param;
        int param1 = (int)parameters[0];
        string param2 = (string)parameters[1];
        Console.WriteLine("Int : {0}  \nString : {1}", param1, param2);

    }

    static void Main(string[] args)
    {
        Thread thread = new Thread(new ParameterizedThreadStart(Method1));
        thread.Start(new object[] { 10, "String value" });
        Console.Read();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM