Tutorial :How to pass parameters to ThreadStart method in Thread?



Question:

How to pass parameters to Thread.ThreadStart() method in C#?

Suppose I have method called 'download'

public void download(string filename)  {      // download code  }  

Now I have created one thread in the main method:

Thread thread = new Thread(new ThreadStart(download(filename));  

error method type expected.

How can I pass parameters to ThreadStart with target method with parameters?


Solution:1

The simplest is just

string filename = ...  Thread thread = new Thread(() => download(filename));  thread.Start();  

The advantage(s) of this (over ParameterizedThreadStart) is that you can pass multiple parameters, and you get compile-time checking without needing to cast from object all the time.


Solution:2

Look at this example:

public void RunWorker()  {      Thread newThread = new Thread(WorkerMethod);      newThread.Start(new Parameter());  }    public void WorkerMethod(object parameterObj)  {      var parameter = (Parameter)parameterObj;      // do your job!  }  

You are first creating a thread by passing delegate to worker method and then starts it with a Thread.Start method which takes your object as parameter.

So in your case you should use it like this:

    Thread thread = new Thread(download);      thread.Start(filename);  

But your 'download' method still needs to take object, not string as a parameter. You can cast it to string in your method body.


Solution:3

You want to use the ParameterizedThreadStart delegate for thread methods that take parameters. (Or none at all actually, and let the Thread constructor infer.)

Example usage:

var thread = new Thread(new ParameterizedThreadStart(download));  //var thread = new Thread(download); // equivalent    thread.Start(filename)  


Solution:4

You could also delegate like so...

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


Solution:5

You can encapsulate the thread function(download) and the needed parameter(s)(filename) in a class and use the ThreadStart delegate to execute the thread function.

public class Download  {      string _filename;        Download(string filename)      {         _filename = filename;      }        public void download(string filename)      {         //download code      }  }    Download = new Download(filename);  Thread thread = new Thread(new ThreadStart(Download.download);  


Solution:6

In Additional

    Thread thread = new Thread(delegate() { download(i); });      thread.Start();  


Solution:7

How about this: (or is it ok to use like this?)

var test = "Hello";  new Thread(new ThreadStart(() =>  {      try      {          //Staff to do          Console.WriteLine(test);      }      catch (Exception ex)      {          throw;      }  })).Start();  


Solution:8

According to your question...

How to pass parameters to Thread.ThreadStart() method in C#?

...and the error you encountered, you would have to correct your code from

Thread thread = new Thread(new ThreadStart(download(filename));  

to

Thread thread = new Thread(new ThreadStart(download));  thread.Start(filename);  



However, the question is more complex as it seems at first.

The Thread class currently (4.7.2) provides several constructors and a Start method with overloads.

These relevant constructors for this question are:

public Thread(ThreadStart start);  

and

public Thread(ParameterizedThreadStart start);  

which either take a ThreadStart delegate or a ParameterizedThreadStart delegate.

The corresponding delegates look like this:

public delegate void ThreadStart();  public delegate void ParameterizedThreadStart(object obj);  

So as can be seen, the correct constructor to use seems to be the one taking a ParameterizedThreadStart delegate so that some method conform to the specified signature of the delegate can be started by the thread.

A simple example for instanciating the Thread class would be

Thread thread = new Thread(new ParameterizedThreadStart(Work));  

or just

Thread thread = new Thread(Work);  

The signature of the corresponding method (called Work in this example) looks like this:

private void Work(object data)  {     ...  }  

What is left is to start the thread. This is done by using either

public void Start();  

or

public void Start(object parameter);  

While Start() would start the thread and pass null as data to the method, Start(...) can be used to pass anything into the Work method of the thread.

There is however one big problem with this approach: Everything passed into the Work method is cast into an object. That means within the Work method it has to be cast to the original type again like in the following example:

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.

As a solution you would expect to get a generic ParameterizedThreadStart delegate like ParameterizedThreadStart<T> where T would be the type of data you want to pass into the Work method. Unfortunately something like this does not exist (yet?).

There is however a suggested solution to this issue. It involves creating a class which contains both, the data to be passed to the thread as well as the method that represents the worker method like this:

public class ThreadWithState  {      private string message;        public ThreadWithState(string message)      {          this.message = message;      }        public void Work()      {          Console.WriteLine($"I, the thread write: {this.message}");      }  }  

With this approach you would start the thread like this:

ThreadWithState tws = new ThreadWithState("I've got some text");  Thread thread = new Thread(tws.Work);    thread.Start();  

So in this way you simply avoid casting around and have a typesafe way of providing data to a thread ;-)


Solution:9

here is the perfect way...

private void func_trd(String sender)  {        try      {          imgh.LoadImages_R_Randomiz(this, "01", groupBox, randomizerB.Value); // normal code            ThreadStart ts = delegate          {              ExecuteInForeground(sender);          };            Thread nt = new Thread(ts);          nt.IsBackground = true;            nt.Start();        }      catch (Exception)      {        }  }    private void ExecuteInForeground(string name)  {       //whatever ur function      MessageBox.Show(name);  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »