How do you start a thread with parameters in C#?
One of the 2 overloads of the Thread constructor takse a ParameterizedThreadStart delegate which allows you to pass a single parameter to the start method. Unfortunately though it only allows for a single parameter and it does so in an unsafe way because it passes it as object. I find it's much easier to use a lambda expression to capture the relevant parameters and pass them in a strongly typed fashion.
Try the following
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) {
...
}
Yep :
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
You can use lambda expressions
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
this is so far the best answer i could find, it's fast and easy.
Simple way using lambda like so..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
OR you could even delegate using ThreadStart like so...
private void DoSomething(int param1, string param2)
{
//DO SOMETHING...
ThreadStart ts = delegate
{
if (param1 > 0) DoSomethingElse(param2, "param3");
};
new Thread(ts).Start();
//DO SOMETHING...
}
OR using .NET 4.5+ even cleaner like so..
private void DoSomething(int param1, string param2)
{
//DO SOMETHING..
void ts()
{
if (param1 > 0) DoSomethingElse(param2, "param3");
}
new Thread(ts).Start();
//DO SOMETHING..
}
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
The parameter type must be an object.
EDIT:
While this answer isn't incorrect I do recommend against this approach. Using a lambda expression is much easier to read and doesn't require type casting. See here: https://stackoverflow.com/a/1195915/52551
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"
}
}
As has already been mention in various answers here, 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 ;-)
I was having issue in the passed parameter.
I passed integer from a for loop to the function and displayed it , but it always gave out different results. like (1,2,2,3) (1,2,3,3) (1,1,2,3) etc with ParametrizedThreadStart delegate.
this simple code worked as a charm
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
The ParameterizedThreadStart takes one parameter. You can use that to send one parameter, or a custom class containing several properties.
Another method is to put the method that you want to start as an instance member in a class along with properties for the parameters that you want to set. Create an instance of the class, set the properties and start the thread specifying the instance and the method, and the method can access the properties.
You could use a ParametrizedThreadStart delegate:
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
You can use the BackgroundWorker RunWorkerAsync method and pass in your value.
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`
}
}
I propose using Task<T>instead of Thread; it allows multiple parameters and executes really fine.
Here is a working example:
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;
}
}
A very simple and convenient way using lambda expression can be like this:
Thread thread = new Thread( (param) => {
string name = param as string;
// rest of code goes here.
});
thread.Start("MyName");
This way a lambda expression can have parameters and run inline code in a separate thread.
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() + " ");
}
}
}
}
Related
async void Main()
{
T0.TT();
}
private class T0
{
[ThreadStatic] private static int test;
public static async void TT()
{
test = 4;
var continuation = new System.Threading.Tasks.TaskCompletionSource<int>(System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously);
var th = new Thread(() => { Thread.Sleep(500); Console.WriteLine(test); test = 3; continuation.TrySetResult(5); test = 7; });
th.Start();
Console.WriteLine(await continuation.Task);
Console.WriteLine(test);
}
}
Output:
0
5
3
So without the System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously this was written to demonstrate the rest of the async method runs on the thread created by new Thread(). However with System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously it still somehow finds that specific [ThreadStatic] value that is set in the newly created thread (thus can't be a TaskScheduler thread) and cleared as soon as TrySetResult returns.
What the hey? How is this happening?
You should be passing TaskCreationOptions.RunContinuationsAsynchronously, not TaskContinuationOptions.RunContinuationsAsynchronously.
Passing TaskContinuationOptions.RunContinuationsAsynchronously will call the overload that takes an object parameter, treating it as a "state" object and not as a flag controlling the TCS behavior.
Class Client{
main(){
MyRequest m = new MyRequest();
m.function();
}
onSucess(string s){
Debug.log("i get data from network:"+s);
}
}
Class Network{
sendMyrequest(MyRequest r){
Thread thread = new Thread(() => sendMyrequestTask(r));
thread.start();
}
private void sendMyrequestTask(MyRequest r){
if(...){
//call delegate function onSucess(string s)
}
}
}
Class MyRequest{
private Network network;
function(){
//do something
network.sendMyrequest(MyRequest r);
}
}
in this case, callback function onSucess(string s) should be a delegate, or a interface, how and where should I implement it? Any suggestion would be appreciate. Thanks in advance!!
Edit: this problem is like: A call B,B call C, when C's job is done, C should call A. How to implement this?
Thanks all guys. I implement in this way.
public interface CallbackFunction{
public onSucess(string s);
}
Class Client:CallbackFunction{
main(){
MyRequest m = new MyRequest();
m.function(this);
}
onSucess(string s){
Debug.log("i get data from network:"+s);
}
}
Class Network{
sendMyrequest(MyRequest r,CallbackFunction c){
Thread thread = new Thread(() => sendMyrequestTask(r,c));
thread.start();
}
private void sendMyrequestTask(MyRequest r,CallbackFunction c){
if(...){
//call delegate function onSucess(string s)
c.onSucess("bla bla bla");
}
}
}
Class MyRequest{
private Network network;
function(CallbackFunction c){
//do something
network.sendMyrequest(this,c);
}
}
You can use async and `await.
For more info :
Many methods do not immediately return. A method may need to query an external source. This takes time. With async and await, we formalize and clarify how asynchronous, non-blocking methods begin and end.
http://msdn.microsoft.com/en-us/library/hh191443.aspx
http://msdn.microsoft.com/en-us/library/hh156513.aspx
By using the Action<> delegate as a constructor argument in MyRequest we can achieve something like this.
You can replace the Action<> type with any other delegate you might want to use. Action<> or Func<> should cover just about anything.
By the way, your code, and hence my code below is not the observer pattern.
public class Client
{
static void Main(string[] args)
{
var client = new MyRequest(OnSuccess);
client.Function();
//Output:
//I'm in the callback
//Foo.Bar()
Console.ReadKey();
}
static void OnSuccess(string result)
{
Console.WriteLine("I'm in the callback");
Console.WriteLine(result);
}
}
public class Network
{
public void SendMyRequest(MyRequest request)
{
var result = "Foo.Bar()";
if (!String.IsNullOrEmpty(result))
{
request.SuccessCallback(result);
}
}
}
public class MyRequest
{
public Action<string> SuccessCallback { get; private set; }
private Network _network;
public MyRequest(Action<string> successCallback)
{
_network = new Network();
SuccessCallback = successCallback;
}
public void Function()
{
_network.SendMyRequest(this);
}
}
It looks like you want to implement something similar to WebClient.DownloadStringCompleted event. Which uses following delegate type:
public delegate void DownloadStringCompletedEventHandler(
Object sender
DownloadStringCompletedEventArgs e)`
with following usage pattern:
WebClient client = new WebClient ();
client.DownloadStringCompleted += DownloadStringCallback2;
client.DownloadStringAsync (new Uri(address));
Note: if you don't expect multiple listeners using async/await will lead to much easier to understand code.
I'm trying to pass parameters through the following:
Thread thread = new Thread(new ParameterizedThreadStart(DoMethod));
Any idea how to do this? I'd appreciate some help
lazyberezovsky has the right answer. I want to note that technically you can pass an arbitrary number of arguments using lambda expression due to variable capture:
var thread = new Thread(
() => DoMethod(a, b, c));
thread.Start();
This is a handy way of calling methods that don't fit the ThreadStart or ParameterizedThreadStart delegate, but be careful that you can easily cause a data race if you change the arguments in the parent thread after passing them to the child thread's code.
Use overloaded Thread.Start method, which accepts object (you can pass your custom type or array if you need several parameters):
Foo parameter = // get parameter value
Thread thread = new Thread(new ParameterizedThreadStart(DoMethod));
thread.Start(parameter);
And in DoMethod simply cast argument to your parameter type:
private void DoMethod(object obj)
{
Foo parameter = (Foo)obj;
// ...
}
BTW in .NET 4.0 and above you can use tasks (also be careful with race conditions):
Task.Factory.StartNew(() => DoMethod(a, b, c));
Instead of creating a class to pass in multiple parameters as #user1958681 has done, you could use anonymous types, then just use the dynamic typing to extract your parameters.
class MainClass
{
int A = 1;
string B = "Test";
Thread ActionThread = new Thread(new ParameterizedThreadStart(DoWork));
ActionThread.Start(new { A, B});
}
Then in DoWork
private static void DoWork(object parameters)
{
dynamic d = parameters;
int a = d.A;
string b = d.B;
}
Another way to archive what you want, is by returning a delegate within your function / method. Take the following example:
class App
{
public static void Main()
{
Thread t = new Thread(DoWork(a, b));
t.Start();
if (t.IsAlive)
{
t.IsBackground = true;
}
}
private static ThreadStart DoWork(int a, int b)
{
return () => { /*DoWork*/ var c = a + b; };
}
}
new Thread(() => { DoMethod(a, b, c); }).Start();
or
new Thread(() => DoMethod(a, b, c)).Start();
// Parameters to pass to ParameterizedThreadStart delegate
// - in this example, it's an Int32 and a String:
class MyParams
{
public int A { get; set; }
public string B { get; set; }
// Constructor
public MyParams(int someInt, string someString)
{
A = someInt;
B = someString;
}
}
class MainClass
{
MyParams ap = new MyParams(10, "Hello!");
Thread t = new Thread(new ParameterizedThreadStart(DoMethod));
t.Start(ap); // Pass parameters when starting the thread
}
class Program
{
public static void Main()
{
MyClass myClass = new MyClass();
ParameterizedThreadStart pts = myClass.DoMethod;
Thread thread1 = new Thread(pts);
thread1.Start(20); // Pass the parameter
Console.Read();
}
}
class MyClass
{
private int Countdown { get; set; }
public void DoMethod(object countdown) // Parameter must be an object and method must be void
{
Countdown = (int) countdown;
for (int i = Countdown; i > 0; i--)
{
Console.WriteLine("{0}", i);
}
Console.WriteLine("Finished!");
}
}
Is there any way so that you can call a function with a variable?
variable+"()";
or something like that, or would I have to use if statements?
A switch seems like it might be the answer, so if the variable's value=var1 I want it to execute var1(); if the value is var2 I want it to execute var2(); how would I code it?
Basically, I am trying to find a cleaner alternative to
if (variable == var1)
{
var1();
}
if (variable == var2)
{
var2();
}
It would be possible to use reflection to find a method in an object and call that method, but the simplest and fastest would be to simply use a switch:
switch (variable) {
case "OneMethod": OneMethod(); break;
case "OtherMethod": OtherMethod(); break;
}
You could use Reflection http://msdn.microsoft.com/en-us/library/ms173183(v=vs.80).aspx to access any function or member by name. It takes some getting used to though. It also has performance issues, so if you can avoid using it, you should.
This is what delegates are for:
Action f = ()=>Console.WriteLine("foo");
f();
I assume using strings is not actually a requirement.
You can use delegates. MSDN: http://msdn.microsoft.com/en-us/library/900fyy8e(v=vs.71).aspx
Exa:
public delegate void TestDelegate();
class TestDelegate
{
public static void Test()
{
Console.WriteLine("In Test");
}
public static void Main()
{
TestDelegate testDelegate = new TestDelegate(Test);
testDelegate();
}
}
You can use the MethodInfo class
Type yourtype = yourObject.GetType();
MethodInfo method = yourtype.GetMethod(variable);
var result = method.Invoke(yourObject,null);
string className = "My.Program.CoolClass"; //including namespace
string method= "Execute";
var type = Type.GetType(className);
var method = type.GetMethod(method);
method.Invoke(classObj, null);
Check out this post.
Use reflection.
http://dotnetslackers.com/Community/blogs/haissam/archive/2007/07/25/Call-a-function-using-Reflection.aspx
You can use MethodMethodInfo.
http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx
http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx
Here's a sample how you can call a method via reflection:
public class MyClass
{
public void PrintHello()
{
Console.WriteLine("Hello World");
}
}
//...
public void InvokeMethod(object obj, string method)
{
// call the method
obj.GetType().GetMethod(method).Invoke(obj, null);
}
//...
var o = new MyClass();
var method = "PrintHello";
//...
InvokeMethod(o, method);
(I will complete #Matthew's excellent answer):
var x = (Action) ( ()=>Print("foo") );
x();
p.s. you can fully variable names too:
private Dictionary<string, dynamic> my = new Dictionary<string, dynamic>();
my["x"] = .....
my["x"]();
public class FunctionTest
{
void Main()
{
Action doSomething;
doSomething = FirstFunction;
doSomething();
doSomething = SecondFunction;
doSomething();
}
void FirstFunction()
{
Console.Write("Hello, ");
}
void SecondFunction()
{
Console.Write("World!\n");
}
}
output:
Hello, World!
Doesn't get too much simpler than that.
How would I call a method with the below header on a thread?
public void ReadObjectAsync<T>(string filename)
{
// Can't use T in a delegate, moved it to a parameter.
ThreadStart ts = delegate() { ReadObjectAcync(filename, typeof(T)); };
Thread th = new Thread(ts);
th.IsBackground = true;
th.Start();
}
private void ReadObjectAcync(string filename, Type t)
{
// HOW?
}
public T ReadObject<T>(string filename)
{
// Deserializes a file to a type.
}
Why can't you just do this...
public void ReadObjectAsync<T>(string filename)
{
ThreadStart ts = delegate() { ReadObject<T>(filename); };
Thread th = new Thread(ts);
th.IsBackground = true;
th.Start();
}
private void ReadObject<T>(string filename)
{
// Deserializes a file to a type.
}
I assume you may have good reasons for using a free-running Thread as opposed to the .NET thread pool, but just for reference, this is quite easy to do in C# 3.5+ with the thread pool:
public void ReadObjectAsync<T>(string filename, Action<T> callback)
{
ThreadPool.QueueUserWorkItem(s =>
{
T result = ReadObject<T>(fileName);
callback(result);
});
}
I put the callback in there because I assume that you probably want to do something with the result; your original example (and the accepted answer) doesn't really provide any way to gain access to it.
You would invoke this method as:
ReadObjectAsync<MyClass>(#"C:\MyFile.txt", c => DoSomethingWith(c));
It would be easy to make this truly generic...
public void RunAsync<T, TResult>(Func<T, TResult> methodToRunAsync, T arg1,
Action<TResult> callback)
{
ThreadPool.QueueUserWorkItem(s =>
{
TResult result = methodToRunAsync(arg1);
callback(result);
});
}