Hello i am trying to pass the current index of a loop inside a thread lambda method and print it.The method will print only the last value of the index.
class Program {
public static EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
public static EventWaitHandle autohandle = new EventWaitHandle(false, EventResetMode.AutoReset);
static readonly int ThreadNum=3;
static void Main(string[] args) {
object lk = new object();
new Thread(() => {
while (true) {
var key = Console.ReadKey();
if(key.Key==ConsoleKey.A) {
handle.Set();
} else {
handle.Reset();
}
Thread.Sleep(3000);
}
}).Start();
for(int i=0;i<ThreadNum;i++) {
new Thread(() => {
int val = i;
Console.WriteLine($"Thread:{val} created");
while (true) {
handle.WaitOne();
Console.WriteLine($"From thread:{val}");
Thread.Sleep(1000);
}
}).Start();
}
Console.WriteLine("Hello World!");
}
}
Can someone explain to me why would i get only the last value of the index.I understand the index gets clojured (a class gets created which copies the index value) but when the first iteration enters the thread method it should clojure i=0 and keep it that way.
I think that the behaviour you are seeing is because the loop is iterating before the local variable 'val' is assigned. So by the time the statement
int val = i;
is executed for the first time, the loop has already iterated 3 times, so you get 'val' set to the last value of i.
When I run it, I get variable behaviour, due to the relative speed at which threads are created.
To get the behaviour I think you want, you need to capture the count of the loop iteration locally, like this.
class Program
{
public static EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
public static EventWaitHandle autohandle = new EventWaitHandle(false, EventResetMode.AutoReset);
static readonly int ThreadNum = 3;
static void Main(string[] args)
{
object lk = new object();
new Thread(() => {
while (true)
{
var key = Console.ReadKey();
if (key.Key == ConsoleKey.A)
{
handle.Set();
}
else
{
handle.Reset();
}
Thread.Sleep(3000);
}
}).Start();
for (int i = 0; i < ThreadNum; i++)
{
int temp = i;
new Thread(() => ThreadMethod(temp)).Start();
}
Console.WriteLine("Hello World!");
}
private static void ThreadMethod(object obj)
{
int val = (int)obj;
Console.WriteLine($"Thread:{val} created");
while (true)
{
handle.WaitOne();
Console.WriteLine($"From thread:{val}");
Thread.Sleep(1000);
}
}
}
Related
I am starting with threads and wrote for the sake of learning the following simple program, which later would be used to calculate about 100,000 times a formula (it is a relatively simple one but which takes an iterated range of values).
The problem with it is that I expected every thread to execute in almost no time and thus the complete program to finish nearly immediately, but the fact is that everything runs too slow (about 10s)...
static readonly double TotalIterations = 1000;
public static Iterations ActualIterations = new Iterations();
public static void Main()
{
var par1 = "foo";
var par2 = "boo";
var par3 = 3;
for (int i = 0; i < TotalIterations; i++)
{
new Thread(() => new Calculations().Calculate(par1, par2, par3)).Start();
}
AwaitingThreads();
}
static void AwaitThreads()
{
Console.WriteLine("Awaiting threads to finished...");
while (true)
{
lock (ActualIterations)
{
if (ActualIterations.Progress() == TotalIterations) break;
}
Thread.Sleep(1 * 1000);
}
Console.WriteLine("All threads finished!");
}
public class Calculations {
public bool Calculate(string par1, string par2, int par3)
{
// ...
bool result = false;
lock (ActualIterations)
{
ActualIterations.Incr();
}
return result;
}
}
public class Iterations
{
int progress = 0;
public void Incr()
{
progress++;
}
public int Progress()
{
return progress;
}
}
I also tried using a ThreadPool like this, but there was no improvement...
static readonly double TotalIterations = 1000;
static string par1 = "foo";
static string par2 = "boo";
static int par3 = 3;
public static Iterations ActualIterations = new Iterations();
public static void Main()
{
ThreadPool.QueueUserWorkItem(MyThreadPool);
AwaitThreads();
}
static void AwaitThreads()
{
Console.WriteLine("Awaiting threads to finished...");
while (true)
{
lock (ActualIterations)
{
if (ActualIterations.Progress() == TotalIterations) break;
}
Thread.Sleep(1 * 1000);
}
Console.WriteLine("All threads finished!");
}
static void MyThreadPool(Object stateInfo)
{
for (int i = 0; i < TotalIterations; i++)
{
new Thread(() => new Calculations().Calculate(par1, par2, par3)).Start();
}
}
public class Calculations {
public bool Calculate(string par1, string par2, int par3)
{
// ...
bool result = false;
lock (ActualIterations)
{
ActualIterations.Incr();
}
return result;
}
}
public class Iterations
{
int progress = 0;
public void Incr()
{
progress++;
}
public int Progress()
{
return progress;
}
}
When I quit using threads in this example and use a static method, executing it sequentially in my for loop, the program finishes in 1s...
Can anybody enlighten me what I am doing wrong here with those threads?
The problem with it is that I expected every thread to execute in almost no time
Right. You're ignoring the fact that creating a new thread is a relatively expensive operation. Far, far more expensive than "acquiring a lock and incrementing an integer" which is the work you're doing in the thread.
To give a real world comparison, it's a little like ordering a new car, waiting it to be delivered, and then driving it 1km. That's going to be slower than just walking 1km.
Using the thread pool would be faster, but you're not using it correctly - you're launching one thread pool task which then creates all the other threads again.
I would encourage you to look at using Task<T> instead, which normally uses the thread pool under the hood, and is a generally more modern abstraction for this sort of work.
This is the way to proceed doing what you wanted to do:
class Program
{
static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() =>
{
Console.WriteLine("Calculations " + DateTime.Now);
}));
}
Task.WaitAll(tasks.ToArray());
}
}
Tasks are actually optimized and programmer-friendly to use if you need to work with threads.
Another advice i want to give you is to create an Object just for locking purposes, example:
class Program
{
private static Object _locker = new Object();
static void Main(string[] args)
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() =>
{
lock (_locker)
{
Console.WriteLine("Calculations " + DateTime.Now);
}
}));
}
Task.WaitAll(tasks.ToArray());
}
}
I see the problem in the AwaitThreads method.
It uses the same lock (ActualIterations) as working thread and it makes working threads to wait for shared resource additionally.
Also (as it was mentioned by #Euphoric) the thread working code you have shown is just about single increment and it uses the shared resource between all threads.
You have to change it in some another way and try to avoid shared resource usage in multi threaded environment.
For example, if you need to make some calculation on huge data array you have to feed each thread own data part to be processed and then wait for all tasks to be finished. There is Task concept and Task.WaitAll
I'm currently running into a problem with multithreading and accessing a static list. A static list holds all items with several properties. The items are identified with a Guid. A main work thread changes some properties for any item in the static list. The child threads all have their own Guid, with this Guid they read their own item in the static list. And after a specific event they remove their assigned element from the static list.
To get to the source I have broken down my code to the essential methods and classes. The work thread has the following simplified code
public void RunWork()
{
Random random = new Random();
Int32 index = -1;
while (!Kill)
{
Thread.Sleep(1);
if (MainWindow.Clients != null)
{
index = random.Next(0, MainWindow.Clients.Count);
MainWindow.Clients[index].State = MainWindow.RandomString(9);
}
}
}
Each child thread has the following simplified code
public void RunChild()
{
Random random = new Random();
while (!Kill)
{
Thread.Sleep(100);
if (MainWindow.Clients.Any(x => x.Id == Id))
{
this.State = MainWindow.Clients.First(x => x.Id == Id).State;
}
Thread.Sleep(random.Next(50));
if (random.Next(100) % 90 == 0)
{
Kill = true;
MainWindow.Clients.RemoveAll(x => x.Id == Id);
}
}
}
If a child removes itself from the MainWindow.Clients list the work thread throws a exception, that the index it is trying to access does not exist.
I have added lock statments around every access of MainWindow.Clients but this does not prevent the work thread from accessing a deleted item. I have also tried Monitor.Enter(MainWindow.Clients) and Monitor.Exit(MainWindow.Clients) but with the same result as with lock.
The static list MainWindow.Clients is created before any thread runs and never gets recreated or disposed.
If the lock statement is set around this block of code in the RunWork() method
lock (MainWindow.Clients)
{
Thread.Sleep(1);
if (MainWindow.Clients != null)
{
index = random.Next(0, MainWindow.Clients.Count);
MainWindow.Clients[index].State = MainWindow.RandomString(9);
}
}
Why does it not block the child threads from changing the list between the lines
where the random index is set and the list gets accessed?
Update 1:
The following code still throws a IndexOutOfRangeException at MainWindow.Clients[index].State = MainWindow.RandomString(9);:
public void RunWork()
{
Random random = new Random();
Int32 index = -1;
while (!Kill)
{
Thread.Sleep(1);
if (MainWindow.Clients != null)
{
lock (MainWindow.Clients)
{
index = random.Next(0, MainWindow.Clients.Count);
MainWindow.Clients[index].State = MainWindow.RandomString(9);
}
}
}
}
public void RunChild()
{
Random random = new Random();
while (!Kill)
{
Thread.Sleep(100);
if (MainWindow.Clients.Any(x => x.Id == Id))
{
this.State = MainWindow.Clients.First(x => x.Id == Id).State;
}
Thread.Sleep(random.Next(50));
if (random.Next(100) % 90 == 0)
{
Kill = true;
lock (MainWindow.Clients)
{
MainWindow.Clients.RemoveAll(x => x.Id == Id);
}
}
}
}
Update 2: Here is the complete code for the quick sample application
Update 3: I have edited my code and wrapped all accesses of MainWindow.Clients with lock statements. But still the threads access the variable while it is locked:
I'm not sure what exactly you are trying to achieve, but I've written something that might help you find the correct solution. Sorry for the lack of correctness - tight schedule ;-)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace ConcurrentCollectionTest
{
internal class Client
{
public string State
{
get; set;
}
public string Name
{
get;
internal set;
}
}
internal class MainWindow
{
private ConcurrentDictionary<int, Client> _dict = new ConcurrentDictionary<int, Client>();
public IDictionary<int, Client> Clients
{
get
{
return _dict;
}
}
}
internal class Program
{
private static bool killAll = false;
private static MainWindow mainWindow = new MainWindow();
private static int id = -100;
private static string state = "Initial";
private static Random random = new Random();
private static object lockObject = new object();
internal static string RandomString(int v)
{
int k = random.Next(0, v);
return k.ToString();
}
public static void RunChild()
{
Debug.WriteLine($"child running {Thread.CurrentThread.Name}");
bool killThis = false;
while (!killThis && !killAll)
{
Thread.Sleep(100);
Client client = null;
if (mainWindow.Clients.TryGetValue(id, out client))
{
state = client.State;
}
Thread.Sleep(random.Next(50));
if (random.Next(100) % 90 == 0)
{
Debug.WriteLine($"killing {Thread.CurrentThread.Name}");
killThis = true;
lock (lockObject)
{
mainWindow.Clients.Remove(id);
}
}
}
}
public static void RunWork()
{
Console.WriteLine("RunWork");
Random random = new Random();
Int32 index = -1;
while (!killAll)
{
if (!mainWindow.Clients.Any())
{
killAll = true;
break;
}
Thread.Sleep(100);
// edit: still need lock here as count can change in between
Client client = null;
lock (lockObject)
{
index = random.Next(0, mainWindow.Clients.Count);
client = mainWindow.Clients[index];
}
Debug.WriteLine($"Changing {client.Name}");
client.State = RandomString(9);
}
Console.WriteLine("Worker killed");
}
private static void Main(string[] args)
{
Console.WriteLine("Starting. Enter id or kill");
for (int i = 0; i < 100; i++)
{
mainWindow.Clients.Add(i, new Client
{
Name = $"Client {i:000}",
State = "Unknown"
});
}
var worker = new Thread(RunWork);
worker.Start();
var threadList = new List<Thread>();
threadList.Add(worker);
for (int i = 0; i < 10; i++)
{
var thread = new Thread(RunChild)
{
Name = $"Child {i:00}"
};
threadList.Add(thread);
thread.Start();
}
while (!killAll)
{
var str = Console.ReadLine();
if (str.Equals("kill", StringComparison.InvariantCultureIgnoreCase))
{
killAll = true;
break;
}
int enteredId = -1;
if (int.TryParse(str, out enteredId))
{
id = enteredId;
}
}
foreach (var thread in threadList)
{
thread.Join();
}
Console.WriteLine("all dead");
}
}
}
I have a static class A which has a public static ConcurrentQueue.
This class has a method which calls a method of another static class B.
In this method of static class B, a worker thread is started which polls for items in the static ConcurrentQueue of class A. If found, it dequeues the item and processes it.
The same method in class B also starts another thread which checks if the queue of class A is being constantly filled. If the filling occasionally is somehow stuck, a call to a static method in class A is made which resets and restarts the process.
And here comes the problem: When I restart the filling, items are inserted again into the static queue of static class A. But my thread in static class B which checks for items in the queue does not find any items anymore.
So my idea is that in class B I somehow lost the reference to the original static queue of class A. I think I oversee here some principles of static classes, but can not figure out what exactly.
EDIT: Here are some more details.
Main:
public static void Main(string[] args)
{
B.Initialize(8);
A.StartDataStream();
Console.ReadKey();
}
Class A:
class A
{
private static ACOMObject MyCOMObjekt;
public static ConcurrentQueue<PriceItem> Prices = new ConcurrentQueue<PriceItem>();
public static void StartDataStream()
{
DataStream myDataStream = GetDataStream();
FillStream(myDataStream);
B.StartHeartbeatCheck();
Console.WriteLine("Press Key to Exit Stream Call.");
Console.ReadKey();
GC.KeepAlive(myDataStream);
GC.KeepAlive(MyCOMObjekt);
}
private static DataStream GetDataStream()
{
if (MyCOMObjekt== null)
{
MyCOMObjekt= new ACOMObject ();
}
return (DataStream) MyCOMObjekt.DataStream;
}
private static void FillStream(DataStream myDataStream)
{
foreach (var symbol in Symbols.SymbolList)
{
myDataStream.Add(symbolNr, 1);
}
myDataStream.Bid += new _IDataStreamEvents_BidEventHandler(myDataStream_Bid);
myDataStream.Ask += new _IDataStreamEvents_AskEventHandler(myDataStream_Ask);
}
private static void myDataStream_Bid(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Price;
p.Time = Time;
p.IsBid = true;
Prices.Enqueue(p);
}
private static void myDataStream_Ask(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Kurs;
p.Time = Zeit;
p.IsBid = false;
Prices.Enqueue(p);
}
public static void RestartMyCOMProcess()
{
try
{
Process proc = Process.GetProcessesByName("MyCOMProcess")[0];
proc.Kill();
}
catch (Exception)
{
//No Process = fine
}
MyCOMObjekt = null;
DataStream myDataStream = GetDataStream();
myDataStream.Bid -= new _IDataStreamEvents_BidEventHandler(myDataStream_Bid); //probably not necessary...
myDataStream.Ask -= new _IDataStreamEvents_AskEventHandler(myDataStream_Ask); //probably not necessary...
FillStream(myDataStream);
}
}
Class B:
class B
{
private static int countPrices; //Incremented every time a price is taken out of Price Queue
public static void Initialize(int numberOfWorkerThreads)
{
StartWorkers(numberOfWorkerThreads);
}
public static void StartWorkers(int number)
{
for (int j = 0; j < number; j++)
{
Thread t = new Thread(ScanForPrices);
t.Name = "ScanForPrices" + j;
t.Start();
}
}
private static void ScanForPrices()
{
try
{
while (true)
{
PriceItem p;
if (A.Prices.TryDequeue(out p))
{
if (p.IsBid)
{
AnalyzeBidPrice(p);
}
else
{
HandleAskPrice(p);
}
Interlocked.Increment(ref countPrices)
}
else
{
Thread.Sleep(1);
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Price Scan Thread aborted.");
}
}
public static void StartHeartbeatCheck()
{
Thread t = new Thread(CheckHeartBeat);
t.Name = "CheckHeartBeat";
t.Start();
}
private static void CheckHeartBeat()
{
TimeSpan start = new TimeSpan(09, 0, 0); //09 o'clock
TimeSpan end = new TimeSpan(20, 0, 0); //20 o'clock
TimeSpan stopTime = new TimeSpan(20, 5, 0); //20 o'clock and 5 minutes
int countSuccessiveBlockings = 0;
try
{
while (true)
{
Thread.Sleep(5000);
TimeSpan now = DateTime.Now.TimeOfDay;
if ((now > start) && (now < end))
{
int countOld = countPrices;
Thread.Sleep(1000);
if (countOld == countPrices)
{
Console.WriteLine(DateTime.Now + ": Price Stream blocked!");
countSuccessiveBlockings++;
}
else
{
countSuccessiveBlockings = 0;
}
if (countSuccessiveBlockings > 2)
{
A.RestartMyCOMProcess();
countSuccessiveBlockings = 0;
}
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Heartbeat Thread aborted.");
}
}
}
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);
}
}
This is my task class:
public class QueueTask
{
private ManualResetEvent _doneEvent;
Queue<QueueObject> _queu;
public QueueTask(ManualResetEvent doneEvent, Queue<QueueObject> queu)
{
this._doneEvent = doneEvent;
_queu = queu;
}
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine("Thread {0} was started...", threadIndex);
QueueObject element = _queu.Dequeue();
int id = DoSomeLongOperation(element);
Console.WriteLine("Thread {0} was finished... queueObjectID: {1}", threadIndex, id);
_doneEvent.Set();
}
protected virtual int DoSomeLongOperation(QueueObject obj)
{
Random rand = new Random();
Thread.Sleep(rand.Next(5000, 10000));
return obj.ID;
}
}
And this is where I call thread pool:
public static void RunThreadPull(Queue<QueueObject> queue, int batchSize)
{
ManualResetEvent[] doneEvents = new ManualResetEvent[batchSize];
Console.WriteLine("Running batch which consist of 6 objects...");
for (int j = 0; j < batchSize; j++)
{
doneEvents[j] = new ManualResetEvent(false);
QueueTask task = new QueueTask(doneEvents[j], queue);
WaitCallback callback = new WaitCallback(task.ThreadPoolCallback);
ThreadPool.QueueUserWorkItem(callback, j);
}
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("All calculations in current batch were completed!");
}
I need to set timeout to each thread in thread pull. I need to Stop thread and do another action. Don't know what action exactly, let it be method TimeoutExpiredAction(). Is exist any way to do that?