43

Does anyone know how to pass multiple parameters into a Thread.Start routine?

I thought of extending the class, but the C# Thread class is sealed.

Here is what I think the code would look like:

...
    Thread standardTCPServerThread = new Thread(startSocketServerAsThread);

    standardServerThread.Start( orchestrator, initializeMemberBalance, arg, 60000);
...
}

static void startSocketServerAsThread(ServiceOrchestrator orchestrator, List<int> memberBalances, string arg, int port)
{
  startSocketServer(orchestrator, memberBalances, arg, port);
}

BTW, I start a number of threads with different orchestrators, balances and ports. Please consider thread safety also.

11 Answers 11

71

Try using a lambda expression to capture the arguments.

Thread standardTCPServerThread = 
  new Thread(
    unused => startSocketServerAsThread(initializeMemberBalance, arg, 60000)
  );
Sign up to request clarification or add additional context in comments.

4 Comments

How safe is that to execute the expression on a seperate thread?
This is safe - with caveats. It can have some strange side-effects, though, if you tweak your variables immediately after calling this, since you're effectively passing the variables in by reference.
Beacuse of what @Reed Copsey explained don't do :for(int i = 0; i < howMany; i++) { Thread t = new Thread(unused => startSocketServerAsThread( x, y, i) ); t.Start(); }. Use a 'proxy' like int toPass = i;
does this capture references as well?
20

Here is a bit of code that uses the object array approach mentioned here a couple times.

    ...
    string p1 = "Yada yada.";
    long p2 = 4715821396025;
    int p3 = 4096;
    object args = new object[3] { p1, p2, p3 };
    Thread b1 = new Thread(new ParameterizedThreadStart(worker));
    b1.Start(args);
    ...
    private void worker(object args)
    {
      Array argArray = new object[3];
      argArray = (Array)args;
      string p1 = (string)argArray.GetValue(0);
      long p2 = (long)argArray.GetValue(1);
      int p3 = (int)argArray.GetValue(2);
      ...
    }>

1 Comment

@Opus I think the lambda expression, JaredPar's solution, is easier to maintain (read, understand, and update)
12

You need to wrap them into a single object.

Making a custom class to pass in your parameters is one option. You can also use an array or list of objects, and set all of your parameters in that.

Comments

7

Use the 'Task' pattern:

public class MyTask
{
   string _a;
   int _b;
   int _c;
   float _d;

   public event EventHandler Finished;

   public MyTask( string a, int b, int c, float d )
   {
      _a = a;
      _b = b;
      _c = c;
      _d = d;
   }

   public void DoWork()
   {
       Thread t = new Thread(new ThreadStart(DoWorkCore));
       t.Start();
   }

   private void DoWorkCore()
   {
      // do some stuff
      OnFinished();
   }

   protected virtual void OnFinished()
   {
      // raise finished in a threadsafe way 
   }
}

Comments

6

.NET 2 conversion of JaredPar answer

Thread standardTCPServerThread = new Thread(delegate (object unused) {
        startSocketServerAsThread(initializeMemberBalance, arg, 60000);
    });

Comments

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

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

void MyParametrizedMethod(string p,int i)
{
// some code.
}

Comments

3

You can't. Create an object that contain params you need, and pass is it. In the thread function cast the object back to its type.

Comments

2

I've been reading yours forum to find out how to do it and I did it in that way - might be useful for somebody. I pass arguments in constructor which creates for me working thread in which will be executed my method - execute() method.

 using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Threading;
namespace Haart_Trainer_App

{
    class ProcessRunner
    {
        private string process = "";
        private string args = "";
        private ListBox output = null;
        private Thread t = null;

    public ProcessRunner(string process, string args, ref ListBox output)
    {
        this.process = process;
        this.args = args;
        this.output = output;
        t = new Thread(new ThreadStart(this.execute));
        t.Start();

    }
    private void execute()
    {
        Process proc = new Process();
        proc.StartInfo.FileName = process;
        proc.StartInfo.Arguments = args;
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.Start();
        string outmsg;
        try
        {
            StreamReader read = proc.StandardOutput;

        while ((outmsg = read.ReadLine()) != null)
        {

                lock (output)
                {
                    output.Items.Add(outmsg);
                }

        }
        }
        catch (Exception e) 
        {
            lock (output)
            {
                output.Items.Add(e.Message);
            }
        }
        proc.WaitForExit();
        var exitCode = proc.ExitCode;
        proc.Close();

    }
}
}

Comments

1

You can take Object array and pass it in the thread. Pass

System.Threading.ParameterizedThreadStart(yourFunctionAddressWhichContailMultipleParameters) 

Into thread constructor.

yourFunctionAddressWhichContailMultipleParameters(object[])

You already set all the value in objArray.

you need to abcThread.Start(objectArray)

1 Comment

this doesnt work. ParametrizedThreadStart requires to use a single argument of type of Object. When using Object[] as a type instead you get the following error: cannot convert from 'method group' to 'parametrizedThreadStart'
0

You could curry the "work" function with a lambda expression:

public void StartThread()
{
    // ...
    Thread standardTCPServerThread = new Thread(
        () => standardServerThread.Start(/* whatever arguments */));

    standardTCPServerThread.Start();
}

Comments

0

You need to pass a single object, but if it's too much hassle to define your own object for a single use, you can use a Tuple.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.