I would like to know if there is a way to dynamically change the parameters passed to a method when it running in a thread.
For example:
trdColCycl thread = new Thread (() => this.ColorsCycling (true));
trdColCycl.Start();
or
trdColCycl thread = new Thread (new ParameterizedThreadStart (this.ColorsCycling));
trdColCycl.Start(true);
and then I want to pass as a parameter to the thread running the value false ... is it possible?
(in this example I would like to dynamically change the parameter value to exit from a loop inside the thread without using global variables)
Thanks for your help.
You could create a shared variable meant for communicating between two threads
class ArgumentObject
{
public bool isOk;
}
// later
thread1Argument = new ArgumentObject() { isOk = true };
TrdColCycl thread = new Thread (() => this.ColorsCycling (thread1Argument));
trdColCycl.Start();
// much later
thread1Argument.isOk = false;
Edit:
Alternatively, you could pass the bool as reference instead:
bool isOk = true;
TrdColCycl thread = new Thread (() => this.ColorsCycling (ref isOk));
trdColCycl.Start();
// later
isOk = false;
In both cases, you'll have to modify the signature of your method:
// original
void ColorsCycling(bool isOk)
// should be
void ColorsCycling(ArgumentObject argument) // for option 1
// or
void ColorsCycling(ref bool isOk) // for option 2
Related
I want set a property where the value is in another thread
[DllExport]
public static bool Value()
{
bool val = false;
Thread thread = new Thread(async () => val = await getVal());
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return val;
}
public async Task<bool> getVal()
{
bool value = false;
await Task.Factory.StartNew(() =>
{
string rs = new WebClient().DownloadString(url);
if (rs == "1")
value = true;
else
value = false;
});
return value;
}
It always returns false why I use that one is I cant use await in a static [DLLExport] method otherwise the form will freeze.
Edit: I cant use async in a DllExport method
Well starting the Thread really tells you nothing about when the code is being run.
After you call .Start() you tell the thread to run its code, but you have no real control of when the OS decides to actually let the code run.
Im also not sure how using locally defined variables inside the other thread-scope actually works, but I find it hard to think that you can set the value like you are trying to do.
Try googling Monitor.Wait(), Monitor.Pulse() which can be used to let one thread wait for another to finish (one calls Monitor.Wait() and the other calls Monitor.Pulse() when it wants the waiting thread to start executing).
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
How would I go about in creating a thread in C#?
In java I would either implement the Runnable interface
class MyThread implements Runnable{
public void run(){
//metthod
}
and then
MyThread mt = new MyThread;
Thread tt = new Thread(mt);
tt.start()
or I could simply extend the Thread class
class MyThread extends Thread{
public void run(){
//method body
}
and then
MyThread mt = new MyThread
mt.start();
No, contrary to Java, in .NET you can't extend the Thread class because it's sealed.
So to execute a function in a new thread the most naive way is to manually spawn a new thread and pass it the function to be executed (as anonymous function in this case):
Thread thread = new Thread(() =>
{
// put the code here that you want to be executed in a new thread
});
thread.Start();
or if you don't want to use an anonymous delegate then define a method:
public void SomeMethod()
{
// put the code here that you want to be executed in a new thread
}
and then within the same class start a new thread passing the reference to this method:
Thread thread = new Thread(SomeMethod);
thread.Start();
and if you want to pass parameters to the method:
public void SomeMethod(object someParameter)
{
// put the code here that you want to be executed in a new thread
}
and then:
Thread thread = new Thread(SomeMethod);
thread.Start("this is some value");
That's the native way to execute tasks in background threads. To avoid paying the high price of creating new threads you could use one of the threads from the ThreadPool:
ThreadPool.QueueUserWorkItem(() =>
{
// put the code here that you want to be executed in a new thread
});
or using an asynchronous delegate execution:
Action someMethod = () =>
{
// put the code here that you want to be executed in a new thread
};
someMethod.BeginInvoke(ar =>
{
((Action)ar.AsyncState).EndInvoke(ar);
}, someMethod);
And yet another, and more modern way to execute such tasks is to use the TPL (starting from .NET 4.0):
Task.Factory.StartNew(() =>
{
// put the code here that you want to be executed in a new thread
});
So, yeah, as you can see, there are like gazzilions of techniques that could be used to run a bunch of code on a separate thread.
I want to start a new thread for one simple method but that method has variables I need to pass it.
Thread tempmovethread = new Thread(new ThreadStart(widget.moveXYZINCHES(xval,yval,zval));
I am getting the error: "Method name expected".
That is the right method name and I did something very similar to this in an earlier bit of code and it worked, the only difference is the method I called before didnt need any variables to be passed:
executethread = new Thread(new ThreadStart(execute.RunRecipe));
Is it possible to start a new thread and pass the variables like this, or do I have to do it another way?
Use an Action to create the correct delegate type.
Thread tempmovethreading = new Thread(new ThreadStart(new Action(() => widget.moveXYZINCHES(xval,yval,zval)));
tempmovethread = new Thread(new ParametrizedThreadStart(widget.moveXYZINCHES);
tempmovethread.Start(new []{xval,yval,zval});
BUT
you should appropriately change the method's signature like this (assuming the used parameters are of type int:
public void moveXYZINCHES(object state)
{
int xval = (state as int[])[0],yval = (state as int[])[1],zval = (state as int[])[2];
...your code
}
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).