Two parameters to a C# thread - c#

I can send one parameter in the thread
class myThread
{
Thread thread;
public myThread(string name, int st)
{
thread = new Thread(this.Get_IP);
thread.Name = name;
thread.Start(st);//передача параметра в поток
thread.Join();
}
void Get_IP(object st)
{
for (int ii = 0; ii < (int)st; ii++)
{
// smth
}
}
}
But i need to send two of them
for example
for (int ii = (int)st; ii < (int)fi; ii++)
{
// smth
}
there is a way to put 2 params all together
void A(int a, int b) { }
and
ThreadStart starter = delegate { A(0, 10); };
But how can i send them to the thread?

You can pass more parameters to thread by using lambda expresion. Like this:
Thread thread = new Thread(()=>A(5,6));

Put the two variables as members in the class:
class MyThread {
private Thread _thread;
private int _start, _finish;
public MyThread(string name, int start, int finish) {
_start = start;
_finish = finish;
_thread = new Thread(Get_IP);
_thread.Name = name;
_thread.Start();
_thread.Join();
}
void Get_IP() {
for (int ii = _start; ii < _finish; ii++) {
// smth
}
}
}
Note: Calling Join right after starting the thread makes is pretty pointless to use a thread.

The Thread.Start method accepts an object as parameter. You can pass an array of your values.
thread.Start(new object[] { a, b });

Create a class that hold all of the values you need to pass and pass an instance of that class to your thread.

If you need to send 2 parametes, you can send them as any type you like, but in the method that starts new thread, you have to unbox it/them:
void MyMethod()
{
int a = 1;
int b = 2;
int[] data = new[] { a, b };
Thread t = new Thread(new ParameterizedThreadStart(StartThread));
t.Start(data);
}
private void StartThread(object obj)
{
int[] data = obj as int[];
if (data != null)
{
int a = data[0];
int b = data[1];
}
}
NOTE: method that is called by new Thread can only accppt object parameter. What is inside this object is not code`s concern, can be anything, like I boxes 2 integers.
Then you simply unbox the object to your original data types.

Related

Adding a method call to a collection

Given a situation where I have a method SetFooInDevice(), which I call using a property as one of the arguments:
public class Program
{
public static byte Foo { get; set; }
public static void SetFooInDevice(System.IO.Ports.SerialPort sp, byte foo)
{
var txBuffer = new List<byte>();
// Format message according to communication protocol
txBuffer.Add(foo);
sp.Write(txBuffer.ToArray(), 0, txBuffer.Count);
}
public static void Main()
{
var _rnd = new Random();
var _serialPort = new System.IO.Ports.SerialPort("COM1", 9600);
_serialPort.Open();
for (int i = 0; i < 100; i++)
{
Foo = (byte)_rnd.Next(0, 255);
SetFooInDevice(_serialPort, Foo); // <-- How to add this call to a collection?
System.Threading.Thread.Sleep(100);
}
}
}
Is it possible to add the method call to a collection, in a way that the method call can be executed when running through the collection at a later time?
I want to be able to add calls to various methods to a collection, that I can run through and execute later if conditions are met (serial port open, time interval has passed, etc.).
Try this:
public static byte Foo { get; set; }
public static void SetFooInDevice(System.IO.Ports.SerialPort sp, byte foo)
{
var txBuffer = new List<byte>();
// Format message according to communication protocol
txBuffer.Add(foo);
sp.Write(txBuffer.ToArray(), 0, txBuffer.Count);
}
public static void Main()
{
List<Action> listActions = new List<Action>(); // here you create list of action you need to execute later
var _rnd = new Random();
var _serialPort = new System.IO.Ports.SerialPort("COM1", 9600);
_serialPort.Open();
for (int i = 0; i < 100; i++)
{
Foo = (byte)_rnd.Next(0, 255);
var tmpFoo = Foo; // wee need to create local variable, this is important
listActions.Add(() => SetFooInDevice(_serialPort, tmpFoo));
System.Threading.Thread.Sleep(100);
}
foreach (var item in listActions)
{
item(); // here you can execute action you added to collection
}
}
You can check this on MS docs Using Variance for Func and Action Generic Delegates
You can use Action delegate for this purpose like below
private List<Action<System.IO.Ports.SerialPort, byte>> methodCalls
= new List<Action<System.IO.Ports.SerialPort, byte>>();

Threading in c# with locks

I think i'm missing some basics in here and unable to fig out the problem..
Output of below program is not as expected. Can some one help me understand the issue here please.
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
public static void ttt(object obj)
{
Console.WriteLine("B "+ obj);
}
}
I'm expecting to see 0 To 9 in output.. But actual output is as follows..
A 1
B 1
A 1
B 1
A 3
B 3
A 4
B 4
A 5
B 5
A 6
B 6
A 7
B 7
A 8
B 8
A 9
B 9
A 10
B 10
Any help is greatly appreciated.
Please feel free to play around with code in https://dotnetfiddle.net/nYfbMU
Thanks,
Reddy.
Change this:
for (var i = 0; i < 10; i++)
{
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
to this:
for (var i = 0; i < 10; i++)
{
var temp = i;
//Console.WriteLine("Start "+i);
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(temp));
This is a closure issue. See Why is it bad to use an iteration variable in a lambda expression
The reason the original code doesn't work as you expected, and why the temp variable does, is because () => ExecuteInBackground(i) is like saying "at some point in the future, I want this new thread to call the ExecuteInBackground method, passing in whatever value i has when that call is made". Since the loop variable goes into scope at the start of the loop, and out of scope after the loop is finished, the value of i changes between the time you call Thread, and when ExecuteInBackground executes. By using a temp variable inside the loop, that goes out of scope with every iteration of the loop, each thread's call to ExecuteInBackground is essentially getting a different variable with an unchanging value with each call, and the next incrementing of i doesn't mess things up.
This worked for me..
using System;
using System.Threading;
public class Program
{
private static readonly object _lock = new object();
public static void Main()
{
for (var i = 0; i <= 10; i++)
{
fn(i);
}
Console.ReadLine();
}
private static void fn(int i)
{
System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
thread.IsBackground = true;
thread.Start();
}
private static void ExecuteInBackground(Object obj)
{
lock (_lock)
{
Thread.Sleep(500);
Console.WriteLine("A "+obj);
test.ttt(obj);
}
}
}
public static class test
{
//private static readonly object _lock = new object();
public static void ttt(object obj)
{
//lock(_lock)
Console.WriteLine("B "+ obj);
}
}

How to wait for a method to finish on another thread?

I am new to multi-thread programming in C#. My problem is that I don't know how to wait for a method that is being run on another thread to finish, before it can continue to the next line. For example, something like this
public class A
{
int i;
public A()
{
i = 0;
}
protected void RunLoop()
{
while(i < 100)
{
i++;
}
}
public void Start()
{
TimerResolution.TimeBeginPeriod(1);
runThread = new Thread(new ThreadStart(RunLoop));
running = true;
runThread.Start();
}
}
public class B
{
A classAInstance = new A();
A.Start();
Console.Writeline(i);
}
Right now, it prints 0 on the console, which is not what I want (i.e. i = 100).
What is the best way to do this? BTW, I don't have access to the runThread that is created in class A
Thanks.
EDIT:
It was a bit difficult to solve this problem without modifying a lot codes. Therefore, we ended up with adding a condition in the public void Start() with which it can decide whether to run the RunLoop in a separate thread or not. The condition was defined using an Enum field.
public void Start()
{
TimerResolution.TimeBeginPeriod(1);
running = true;
if (runningMode == RunningMode.Asynchronous)
{
runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
else
{
RunLoop();
}
}
And
public enum RunningMode { Asynchronous, Synchronous };
Thanks everyone for help.
The preferred method is to use the Task Parallel Library (TPL) and use Task with await.
If you must use Threads, then use a ManualResetEvent or ManualResetEventSlim to signal the end of a method.
void Main()
{
var a = new A();
a.Start();
a.FinishedEvent.WaitOne();
Console.WriteLine(a.Index);
}
// Define other methods and classes here
public class A
{
ManualResetEvent mre = new ManualResetEvent(false);
int i;
public EventWaitHandle FinishedEvent
{
get { return mre; }
}
public int Index
{
get { return i; }
}
public A()
{
i = 0;
}
protected void RunLoop()
{
while (i < 1000)
{
i++;
}
mre.Set();
}
public void Start()
{
var runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
}
Your life would be so much better with tasks.
Your code could be this simple:
var task = Task.Factory.StartNew(() =>
{
var i = 0;
while (i < 100)
{
i++;
}
return i;
});
Console.WriteLine(task.Result);
I like use Monitor.Wait() and Monitor.Pulse() in conjunction with "lock" operator. It works, but you must be careful, when you use this technique.
I'm added some changes to your code to demonstrate it. Code below are prints i== 100, as you want.
public class A
{
int i;
public object SyncObject
{ get; private set; }
public A()
{
SyncObject = new object();
i = 0;
}
protected void RunLoop()
{
while (i < 100)
{
i++;
}
lock (SyncObject)
{
Monitor.Pulse(SyncObject);
}
}
public void Start()
{
var runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
public void PrintI()
{
Console.WriteLine("I == " + i);
}
}
public class B
{
public static void Run()
{
A classAInstance = new A();
lock (classAInstance.SyncObject)
{
classAInstance.Start();
Monitor.Wait(classAInstance.SyncObject);
}
classAInstance.PrintI();
}
}

Passing a parameter to a thread

I have a problem using threads. There is a class like this:
public class MyThread
{
public void Thread1(int a)
{
for (int i = 0; i < 1000000; i++)
{
j++;
for (int i1 = 0; i1 < 1000; i1++)
{
j++;
}
}
MessageBox.Show("Done From Class");
}
}
and I use this below code for using it:
private void button1_Click(object sender, EventArgs e)
{
MyThread thr = new MyThread();
Thread tid1 = new Thread(new ThreadStart(thr.Thread1));
tid1.Start();
MessageBox.Show("Done");
}
I get error because of Thread1 Parameter (int a),
there isn't any problem when I haven't got any parameter.
How can I fix it?
A preferred method is the first one as you can pass multiple parameters to your method without having to cast to object all the time.
Thread t= new Thread(() => thr.Thread1(yourparameter));
t.Start();
Alternatively, you need to use parameterised thread as you are passing parameter to thread. you can also do
Thread t = new Thread (new ParameterizedThreadStart(thr.Thread1));
t.Start (yourparameter);
ofcourse your parameter has to be of object type for second example.
Threads accept a single object parameter:
public void Thread1(object a1)
{
int a = (int)a1;
...
}
Pass it like this:
Thread t = new Thread(Thread1);
t.Start(100);
You don't normally need to build delegates. Doing new ThreadStart(...) is normally useless from C# 2.0 .
Another (common) solution is to put Thread1 in another object:
public class MyThread
{
public int A;
public void Thread1()
{
// you can use this.A from here
}
}
var myt = new MyThread();
myt.A = 100;
var t = new Thread(myt.Thread1)
t.Start();
This because delegates have a reference to the containing object of the method. Clearly in this way you lose access to the caller's object... But then you could do:
public class MyThread
{
public int A;
public CallerType ParentThis;
public void Thread1()
{
// you can use this.A from here
// You can use ParentThis.Something to access the caller
}
}
var myt = new MyThread();
myt.A = 100;
myt.ParentThis = this;
var t = new Thread(myt.Thread1)
t.Start();
A final common method is to use closures, as suggested by Ehsan Ullah (the example with the () =>)

A robust method of tracking failed workers with ThreadPool

I'm looking for a good method of tracking (counting) which workers have failed when queued with a Threadpool and using WaitHandle.WaitAll() for all threads to finish.
Is Interlocking a counter a good technique or is there a more robust strategy?
Okay, here's an approach that you could take. I've encapsulated the data that we want to track into a class TrackedWorkers. There is a constructor on this class that enables you to set how many workers will be working. Then, the workers are launched using LaunchWorkers which requires a delegate that eats an object and returns a bool. The object represents the input to the worker and the bool represents success or failure depending on true or false being the return value, respectively.
So basically what we do we have an array to track worker state. We launch the workers and set the status corresponding to that worker depending on the return value from the worker. When the worker returns, we set an AutoResetEvent and WaitHandle.WaitAll for all the AutoResetEvents to be set.
Note that there is an nested class to track the work (the delegate) the worker is supposed to do, the input to that work, and an ID used to set the status AutoResetEvent corresponding to that thread.
Note very carefully that once the work is done we are not holding a reference to the work delegate func nor to the input. This is important so that we don't accidentally prevent stuff from being garbage collected.
There are methods for getting the status of a particular worker, as well as all the indexes of the workers that succeeded and all the indexes of the workers that failed.
One last note: I do not consider this code production ready. It is merely a sketch of the approach that I would take. You need to take care to add testing, exception handling and other such details.
class TrackedWorkers {
class WorkerState {
public object Input { get; private set; }
public int ID { get; private set; }
public Func<object, bool> Func { get; private set; }
public WorkerState(Func<object, bool> func, object input, int id) {
Func = func;
Input = input;
ID = id;
}
}
AutoResetEvent[] events;
bool[] statuses;
bool _workComplete;
int _number;
public TrackedWorkers(int number) {
if (number <= 0 || number > 64) {
throw new ArgumentOutOfRangeException(
"number",
"number must be positive and at most 64"
);
}
this._number = number;
events = new AutoResetEvent[number];
statuses = new bool[number];
_workComplete = false;
}
void Initialize() {
_workComplete = false;
for (int i = 0; i < _number; i++) {
events[i] = new AutoResetEvent(false);
statuses[i] = true;
}
}
void DoWork(object state) {
WorkerState ws = (WorkerState)state;
statuses[ws.ID] = ws.Func(ws.Input);
events[ws.ID].Set();
}
public void LaunchWorkers(Func<object, bool> func, object[] inputs) {
Initialize();
for (int i = 0; i < _number; i++) {
WorkerState ws = new WorkerState(func, inputs[i], i);
ThreadPool.QueueUserWorkItem(this.DoWork, ws);
}
WaitHandle.WaitAll(events);
_workComplete = true;
}
void ThrowIfWorkIsNotDone() {
if (!_workComplete) {
throw new InvalidOperationException("work not complete");
}
}
public bool GetWorkerStatus(int i) {
ThrowIfWorkIsNotDone();
return statuses[i];
}
public IEnumerable<int> SuccessfulWorkers {
get {
return WorkersWhere(b => b);
}
}
public IEnumerable<int> FailedWorkers {
get {
return WorkersWhere(b => !b);
}
}
IEnumerable<int> WorkersWhere(Predicate<bool> predicate) {
ThrowIfWorkIsNotDone();
for (int i = 0; i < _number; i++) {
if (predicate(statuses[i])) {
yield return i;
}
}
}
}
Sample usage:
class Program {
static Random rg = new Random();
static object lockObject = new object();
static void Main(string[] args) {
int count = 64;
Pair[] pairs = new Pair[count];
for(int i = 0; i < count; i++) {
pairs[i] = new Pair(i, 2 * i);
}
TrackedWorkers workers = new TrackedWorkers(count);
workers.LaunchWorkers(SleepAndAdd, pairs.Cast<object>().ToArray());
Console.WriteLine(
"Number successful: {0}",
workers.SuccessfulWorkers.Count()
);
Console.WriteLine(
"Number failed: {0}",
workers.FailedWorkers.Count()
);
}
static bool SleepAndAdd(object o) {
Pair pair = (Pair)o;
int timeout;
double d;
lock (lockObject) {
timeout = rg.Next(1000);
d = rg.NextDouble();
}
Thread.Sleep(timeout);
bool success = d < 0.5;
if (success) {
Console.WriteLine(pair.First + pair.Second);
}
return (success);
}
}
The above program is going to launch sixty-four threads. The ith thread has the task of adding the numbers i and 2 * i and printing the result to the console. However, I have added a random amount of sleep (less than one second) to simulate busyness and I flip a coin to determine success or failure of the thread. Those that succeed print the sum they were tasked with and return true. Those that fail print nothing and return false.
Here I have used
struct Pair {
public int First { get; private set; }
public int Second { get; private set; }
public Pair(int first, int second) : this() {
this.First = first;
this.Second = second;
}
}

Categories

Resources