I am currently working on a c# project and I need to have a method which has 1 paramater to run as a thread.
E.g.
public void myMethod(string path)
{
int i = 0;
while (i != 0)
{
Console.WriteLine("Number: " + i);
i++;
}
}
How can I call the above method from another method, but running inside a thread.
Thanks for any help you can provide.
The simplest way is generally to use an anonymous method or lambda expression:
string path = ...;
Thread thread = new Thread(() => MyMethod(path));
thread.Start();
You can use a ParameterizedThreadStart, but I generally wouldn't.
Note that if you do it in a loop, you need to be aware of the normal "closing over the loop variable" hazard:
// Bad
foreach (string path in list)
{
Thread thread = new Thread(() => MyMethod(path));
thread.Start();
}
// Good
foreach (string path in list)
{
string copy = path;
Thread thread = new Thread(() => MyMethod(copy));
thread.Start();
}
new Thread(o => myMethod((string)o)).Start(param);
Simply wrap that method call in a method that takes no parameters, but which calls your method with the right parameter.
public void myWrappingMethod()
{
myMethod(this.Path);
}
public void myMethod(string path)
{
// ...
}
Or if you have lambdas available, simply use one of those (per Jon Skeet's answer).
Related
I need to know how to send data over my threads, I have this code.
new Thread(BattleArena.ArenaGame(12)).Start();
And over BattleArena class I have
public static void ArenaGame(int test)
{
while (true)
{
Console.WriteLine(test);
Thread.Sleep(400);
}
}
But that is not a valid way...
Right now you are "sending" the result of a method call. (Not even compilable). You want to send/execute a function:
new Thread(() => BattleArena.ArenaGame(12)).Start();
Don't use parameterized threads, they are obsolete thanks to lambdas.
To clarify: a thread is not a way to send data. It is a way to execute a function. The the function has to contain the data.
You need to use parameterised threads. Like
ThreadStart start = () => { BattleArena.ArenaGame(12); };
Thread t = new Thread(start);
t.Start();
Or
Thread newThread = new Thread(BattleArena.ArenaGame);
newThread.Start(12);
then change this method as it only takes object as parameter as ThreadStart is not a generic delegate
public static void ArenaGame(object value)
{
int test = (int)value;
while (true)
{
Console.WriteLine(test);
Thread.Sleep(400);
}
}
you should use Parameterized ThreadStart
I'm trying to create a loop which creates a thread for each program in a list, but i'm getting a "method name expected" error upon passing perimeters on the code below;
for (i = 0; i <= programs.Count; i++)
{
checkProcess check = new checkProcess();
// check.isRunning();
string filename = programs[i].Filename;
string filepath = programs[i].Filepath;
mWorkerThread = new Thread(new ThreadStart(check.isRunning(filename, filepath)));
mWorkerThread.Start();
}
I read a little on delegates but couldn't seem to get them to work in the context of my problem. Any help would be greatly appreciated as to what direction i should be heading.
The thread target ought to be something executable and not the result of your method.
mWorkerThread = new Thread(new ThreadStart(check.isRunning(filename, filepath)));
In your case above, you try to create a new instance of ThreadStart with the return value of check.IsRunning(...). What you want is something like
mWorkerThread = new Thread( () => check.isRunning(filename, filepath) );
In your statement mWorkerThread = new Thread(new ThreadStart(check.isRunning(filename, filepath))); check.isRunning is the method name that called on the start of the thread.
Thread t = new Thread(new ThreadStart(ThreadMethod));
t.Start("My Parameter");
// method that will be called
private void ThreadMethod(object parameter)
{
// parameter equals to "My Parameter"
}
Another expect is the anonymous delegate method that make your method inline.. using lambda expression:
Thread t = new Thread(new ThreadStart(()=>ThreadMethod(parmaValue) ));
t.Start("My Parameter");
Ref:
ThreadStart with parameters
I have this class:
public class Statistics
{
List<string> _lsit;
public List<string> ipList
{
get { return _lsit; }
set { _lsit = value; }
}
string _Path = #"C:\Program Files\myApp.exe";
string _Path = "";
ProcessStartInfo ps = null;
public getStatistics(string Path)
{
_Path = Path;
getStatistics();
}
}
I want to start the function Statistics with different Thead and i did somthing like:
Statistics stat = new Statistics (some path);
Thread<List<string>> lList = new Thread<List<string>>(() => tsharkIps.getStatistics());
but the compiler Error says "The non-generic type 'System.Threading.Thread' cannot be used with type arguments"
I did not write all my class and only want to know hot to start the thread
thanks
You need to take a step back to start with and read the compiler error. Thread is not a generic type. It's really not at all clear what you're trying to do here, especially as you haven't even shown a parameterless getStatistics() method (which should be called GetStatistics() to follow .NET naming conventions) and the parameterized getStatistics() method you have shown doesn't have a return type.
Starting a thread with a lambda expression is the easy part:
Thread thread = new Thread(() => CallSomeMethodHere());
thread.Start();
It's not clear how that translates to your sample code though.
Or using the TPL in .NET 4, you can (and probably should use Task or Task<T>):
Task task = Task.Factory.StartNew(() => CallSomeMethodHere());
or
Task<string> task = Task.Factory.StartNew(() => CallSomeMethodReturningString());
It's possible that you really want:
Task<List<string>> statisticsTask = Task.Factory.StartNew(() => {
Statistics statistics = new Statistics(path);
return statistics.ipList();
});
Note that here the constructor is called within the new task - which is important, as it looks like that's probably doing all the work. (That's usually a bad idea to start with, but that's another matter.)
You should look at .NET naming conventions in general, btw...
I have a method which creates different number of requests according to user's input. For each input I have to create an instance of an object and run method from that object in new thread.
It means I never know, how many threads I will need.
And later I will have to access data from each instance that I created before.
So the question is: How can I create different number of requests (and for each request one thread) according to user's input?
An example:
userInput = [start, end, start2, end2, start3, end3]
//for each pair Start-end create instance with unique name or make it other way accessible
Request req1 = new Request('start', 'end')
Request req2 = new Request('start2', 'end2')
Request req3 = new Request('start3', 'end3')
//create thread for each instance
Thread t1 = new Thread(new ThreadStart(req1.GetResponse));
t1.Start();
Thread t2 = new Thread(new ThreadStart(req2.GetResponse));
t2.Start();
Thread t3 = new Thread(new ThreadStart(req3.GetResponse));
t3.Start();
//get data from each instance
string a = req1.result
string b = req2.result
string c = req3.result
In .NET 4, this could be done via Task<T>. Instead of making a thread, you'd write this as something like:
Request req1 = new Request("start", "end");
Task<string> task1 = req1.GetResponseAsync(); // Make GetResponse return Task<string>
// Later, when you need the results:
string a = task1.Result; // This will block until it's completed.
You'd then write the GetRepsonseAsync method something like:
public Task<string> GetRepsonseAsync()
{
return Task.Factory.StartNew( () =>
{
return this.GetResponse(); // calls the synchronous version
});
}
You should NOT create a new thread per Request. Instead take advantage of the ThreadPool, either by using TPL, PLINQ or ThreadPool.QueueUserWorkItem.
An example of how you could do it with PLINQ:
public static class Extensions
{
public static IEnumerable<Tuple<string, string>> Pair(this string[] source)
{
for (int i = 0; i < source.Length; i += 2)
{
yield return Tuple.Create(source[i], source[i + 1]);
}
}
}
class Program
{
static void Main(string[] args)
{
var userinput = "start, end, start2, end2, start3, end3, start4, end4";
var responses = userinput
.Replace(" ", string.Empty)
.Split(',')
.Pair()
.AsParallel()
.Select(x => new Request(x.Item1, x.Item2).GetResponse());
foreach (var r in responses)
{
// do something with the response
}
Console.ReadKey();
}
}
If you are using .NET 3.5 or lower you could use the ThreadPool.QueueUserWorkItem method and if you are using .NET 4.0 use the TPL.
In general I get C#'s lambda syntax. However the anonymous thread syntax isn't completely clear to me. Can someone explain what a thread creation like this is actually doing? Please be as detailed as possible, I'd love to have a sort of step-by-step on the magic that makes this work.
(new Thread(() => {
DoLongRunningWork();
MessageBox.Show("Long Running Work Finished!");
})).Start();
The part that I really don't understand is the Thread(() => ...
When I use this syntax it seems like I remove a lot of the limits of a traditional ThreadStart such as having to invoke on a method that has no parameters.
Thanks for your help!
() => ... just means that the lambda expression takes no parameters. Your example is equivalent to the following:
void worker()
{
DoLongRunningWork();
MessageBox.Show("Long Running Work Finished!");
}
// ...
new Thread(worker).Start();
The { ... } in the lambda let you use multiple statements in the lambda body, where ordinarily you'd only be allowed an expression.
This:
() => 1 + 2
Is equivalent to:
() => { return (1 + 2); }
This is anonymous way to create a thread in C# which just start the thread (because you are using Start();)
Following 2 ways are equivalent. If you need Thread variable to do something (for example block the calling thread by calling thread0.join()), then you use the 2nd one.
new Thread(() =>
{
Console.WriteLine("Anonymous Thread job goes here...");
}).Start();
var thread0= new Thread(() =>
{
Console.WriteLine("Named Thread job goes here...");
});
thread0.Start();
Now the Thread method part. If you see the Thread declaration we have the following (I omitted 3 others).
public Thread(ThreadStart start);
Thread takes a delegate as a parameter. Delegate is reference to a method. So Thread takes a parameter which is a delegate. ThreadStart is declared like this.
public delegate void ThreadStart();
It means you can pass any method to Thread which return void and doesn't take any parameters. So following examples are equivalent.
ThreadStart del = new ThreadStart(ThreadMethod);
var thread3 = new Thread(del);
thread3.Start();
ThreadStart del2 = ThreadMethod;
var thread4 = new Thread(del2);
thread4.Start();
var thread5 = new Thread(ThreadMethod);
thread5.Start();
//This must be separate method
public static void ThreadMethod()
{
Console.WriteLine("ThreadMethod doing important job...");
}
Now we think that ThreadMethod method is doing little work we can make it to local and anonymous. So we don't need the ThreadMethod method at all.
new Thread( delegate ()
{
Console.WriteLine("Anonymous method Thread job goes here...");
}).Start();
You see after delegate to last curly braces is equivalent to our ThreadMethod(). You can further shorten the previous code by introducing Lambda statement (See MSDN). This is just you are using and see how it has been ended up like the following.
new Thread( () =>
{
Console.WriteLine("Lambda statements for thread goes here...");
}).Start();
As there was some answers before I started, I will just write about how additional parameters make their way into lambda.
In short this thing called closure. Lets dissect your example with new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start(); into pieces.
For closure there's a difference between class' fields and local variables. Thus let's assume that transId is class field (thus accessible through this.transId) and others are just local variables.
Behind the scenes if lambda used in a class compiler creates nested class with unspeakable name, lets name it X for simplicity, and puts all local variables there. Also it writes lambda there, so it becomes normal method. Then compiler rewrites your method so that it creates X at some point and replaces access to machine, info and newConfigPath with x.machine, x.info and x.newConfigPath respectively. Also X receives reference to this, so lambda-method could access transId via parentRef.transId.
Well, it is extremely simplified but near to reality.
UPD:
class A
{
private int b;
private int Call(int m, int n)
{
return m + n;
}
private void Method()
{
int a = 5;
a += 5;
Func<int> lambda = () => Call(a, b);
Console.WriteLine(lambda());
}
#region compiler rewrites Method to RewrittenMethod and adds nested class X
private class X
{
private readonly A _parentRef;
public int a;
public X(A parentRef)
{
_parentRef = parentRef;
}
public int Lambda()
{
return _parentRef.Call(a, _parentRef.b);
}
}
private void RewrittenMethod()
{
X x = new X(this);
x.a += 5;
Console.WriteLine(x.Lambda());
}
#endregion
}