This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 3 months ago.
Been working on a program recently and have a question about a problem I ran into. I've solved it, but don't know why it's happening:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() => {(does stuff, uses "i")});
}
Essentially I have 10 known processes I want to run on separate threads. In the thread, the value of the incrementor "i" is used to assign an object to a position in another array (I use locking). Now if I run it as is, I get an out of bounds error and when I debug with code breaks, I find that on that last loop i is equal to 10, when the last value should be 9. When this code isn't threaded, it works perfectly fine.
I decided to try and assign the incrementer to a local variable inside the thread:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() =>
{
localI=i;
(does stuff, uses "localI")
});
}
This had the same issue. I did more reading online and tried a different ordering of it:
for(int i = 0; i<10; i++)
{
localI=i;
Thread t = new Thread (() =>
{
(does stuff, uses "localI")
});
}
And this code works. I can't at all figure out why this works, but the second example didn't. Could anyone help me figure it out?
Thanks
Effectively there are 11 threads, your main thread running the for loop and the threads you spawn.
By the time your 10 new threads run the main loop might well be finished and the value of i will be 10. If you then use this to index an array you will get the out of bounds error.
Your third example assigns i to the localI var, this will keep its value and the individual threads will use that saved value of localI.
It`s simple.
The i variable is run on main thread and for loop reaches 10 value even before the child thread initiates. So, you can add a local variable outside of child threads to get fixed value on every loop.
And, for loop set 10 on i variable, but not run loop, because gets false on checks.
Simple test:
class Program
{
static void Main(string[] args)
{
Test c = new Test();
Console.WriteLine("NonLocal:");
Console.WriteLine(string.Join(",", c.NonLocal));
Console.WriteLine();
Console.WriteLine("Local:");
Console.WriteLine(string.Join(",", c.Local));
Console.ReadLine();
}
}
class Test
{
public object locker;
public List<object> NonLocal; // use List<> for dynamic array
public object[] Local;
public Test()
{
this.locker = new object();
this.NonLocal = new List<object>();
this.Local = new object[10];
// child thread pool
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
int localI = i;
Thread t = new Thread(() =>
{
lock (locker)
{
// adding to result only index
// to see value on i variable on this point
this.NonLocal.Add(i);
// using a fixed local variable
this.Local[localI] = localI;
}
});
threads.Add(t);
t.Start();
}
// wait until threads end
while (true)
{
if (!threads.Any(x => x.IsAlive)) break;
}
}
}
Related
This question already has answers here:
C# "lock" keyword: Why is an object necessary for the syntax?
(3 answers)
Closed 4 years ago.
I do not speak English and I use translator.
I'm wondering when I'm studying thread synchronization.
class MainApp
{
static public int count = 0;
static private object tLock = new object();
static void plus()
{
for (int i = 0; i < 100; i++)
{
lock (tLock)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
}
}
static void minus()
{
for (int i = 0; i < 100; i++)
{
lock (tLock)
{
count--;
Console.WriteLine("minus " + count);
Thread.Sleep(1);
}
}
}
static void Main()
{
Thread t1 = new Thread(new ThreadStart(plus));
Thread t2 = new Thread(new ThreadStart(minus));
t1.Start();
t2.Start();
}
}
Simple thread studying.
static private object tLock = new object();
lock (tLock) << argument value, why object argument??
Why have an object argument on lock?
Well, because it's convenient.
First of all, it's obvious in your code example that you need some shared state between the calls to lock, to declare that two different sections of code are mutually exclusive. If the syntax was just lock { } without a parameter, like this:
public void DoSomestuff()
{
lock
{
// Section A
}
}
public void DoOtherStuff()
{
lock
{
// Section B
}
}
Then either all locks would be mutually exclusive, or would impact only their individual portion of code (so two threads could execute section A and B concurrently, but only one thread at a time could execute A). This would greatly reduce the usefulness of the keyword.
Now that we established that we need a shared state, what this state should be? We could have used a string:
lock ("My Section")
{
// Section A
}
It would work but has a few drawbacks:
You expose yourself to potential collisions between the name of different sections in different libraries
It means that the runtime has to keep a kind of table to associate the string to a lock. Nothing too difficult, but that's some overhead
Instead, the .NET authors went for using an object argument. This solves problem 1/, as you know that another library won't have a reference to your object unless you willingly give it. But this also solves problem 2/, because this allows the runtime to store the lock in the actual object header. That's a pretty neat optimization.
Consider the following (without lock):
for (int i = 0; i < 1000; i++)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
If two threads run simultaneously:
First thread adds one to count which is now 1.
Now second thread takes over and adds one to count which is now 2.
Second thread continues to print plus 2 and loops and again adds one to count which is now 3.
Now the first thread takes over and prints plus 3 which was not intended since count was 1 when WriteLine was to be called.
When adding a locking mechanism (lock) the developer makes sure that a part of the code is atomic, i.e. is run in sequence without interruption.
for (int i = 0; i < 1000; i++)
{
lock (tLock)
{
count++;
Console.WriteLine("plus " + count);
Thread.Sleep(1);
}
}
If you follow the same pattern here:
First thread adds one to count which is now 1.
Now second thread tries to take over but has to wait until the lock is released by the first thread.
First thread prints plus 1 and releases the lock.
Now second thread can take over and add one to count which is now 2.
First thread tries to take over but has to wait until the second thread releases the lock.
Second thread prints plus 2 and releases the lock.
As you can see the increment and WriteLine are now synchronized operations.
Edit
After you changed the question:
The lock keyword requires an object of reference type. It doesn't have to be an object. It can also be a class, interface, delegate, dynamic or string.
public static string a = string.Empty;
public static void Main()
{
lock(a)
{
Console.WriteLine("Hello World");
}
}
See the documentation for more information.
This question already has answers here:
Why is lock(this) {...} bad?
(18 answers)
Closed 8 years ago.
I wanted to understand dangers of lock(this) with some code example. With the code, if everything works well I expect to see 1000 at the end of program.
And that's what I get every time I run it even though I am using lock(this). Why lock(this) works well here?
class Program
{
static void Main(string[] args)
{
Test t = new Test();
for (int x = 0; x < 100; x++)
{
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] = new Thread(t.ProtectedMethod);
threads[i].Start();
}
for (int i = 0; i < 10; i++)
threads[i].Join();
Console.WriteLine("Done with {0}", t.i);
}
}
}
class Test
{
public int i = 0;
public void ProtectedMethod()
{
lock (this)
{
i++;
}
}
}
The lock on this prevents multiple threads to enter the lock code block for the object at the same time. While one thread is in the code block, the other threads are waiting until the current lock on 'this' object is released.
It runs okay because example is too simple. It's equivalent to the case when you lock on some private variable. I say that it will even run fine if you wrap for loop with lock (t) since lock supports recursion.
But imagine if other thread had locked on your variable and entered some infinite loop? Just after you created variable? A deadlock would occur.
Now let's imagine you provide your code with lock (this) as 3rd party dll. You never know how smart will be the consumer of your library...
I want to run multiple threads at a time simultaneously (max 5 threads, for example) and when either one finishes, the new one starts with different data. (one finishes, one new start, two finishes, two new start...)
Main for loop is in main form, but run from a different thread not to block the UI.
When I run it, program adds 5 web browser controls (as a visual progress) and when the page is done loading it removes loaded ones.
The problem is no more controls is being added to the form.
Maybe semaphore is not released properly to allow new ones to start or am I missing something else?
And if I close the program, it doesn't exit, I think it gets blocked on WaitHandle.WaitOne because there are still more jobs to be done.
I removed some non needed data for more code clarity.
Semaphore pool = new Semaphore(5, 5);
Scraper[] scraper = new Scraper[5];
Gecko.GeckoWebBrowser wb = null;
int j = 0;
for (int i = 0; i < arrScrapeboxItems.Count; i++)
{
pool.WaitOne();
bool pustiMe = true;
while (pustiMe)
{
if (scraper[j] == null) scraper[j] = new Scraper();
if (scraper[j].tred == null)
{
ScrapeBoxItems sbi = (ScrapeBoxItems)arrScrapeboxItems[i];
doneEvents.Add(new ManualResetEvent(false)); // this is for WaitHandle.WaitAll after the for loop is done all the items
wb = new Gecko.GeckoWebBrowser();
PoolObjects po = new PoolObjects();
po.link = sbi.link;
// etc...
scraper[j].ThreadsCompleted += new Scraper.ThreadsHandler(frmMain_NextThreadItemsCompleted);
scraper[j].tred = new Thread(new ParameterizedThreadStart(scraper[j].Scrape));
scraper[j].tred.Start(po);
pustiMe = false;
if (j == maxThreads - 1)
j = 0;
else
j++;
break;
}
else if (scraper[j].tred.IsAlive) // if the thread is finished, make room for new thread
{
scraper[j] = null;
}
if (pustiMe) Thread.Sleep(1000);
}
}
// event from Scraper class
void frmMain_ThreadsCompleted()
{
pool.Release();
}
And the Scraper class look like:
public void Scrape(object o)
{
po = (PoolObjects)o;
// do stuff with po
po.form.Invoke((MethodInvoker)delegate
{
po.form.Controls.Add(po.wb);
po.wb.DocumentCompleted += new EventHandler<Gecko.Events.GeckoDocumentCompletedEventArgs>(wb_DocumentCompleted);
po.wb.Navigate(po.link);
});
}
void wb_DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e)
{
var br = sender as Gecko.GeckoWebBrowser;
if (br.Url == e.Uri)
{
form.Controls.Remove(po.wb);
ThreadsCompleted();
manualReset.Set();
}
}
Either you have a typo or a huge bug. You have
else if (scraper[j].tred.IsAlive)
{
scraper[j] = null;
}
I think you want if (!scraper[j].tred.IsAlive). Otherwise, you'll end up overwriting an active Scraper reference in the array.
More to the point, trying to maintain that array of Scraper objects is causing you a lot of complication that you really don't need. You already have the semaphore controlling how many concurrent threads you can have, so the array of Scraper objects is unnecessary noise.
Also, you don't want a whole bunch of ManualResetEvent objects to wait on. WaitAll can't wait on more than 63 items, so if you have more than that in your items list, WaitAll isn't going to do it for you. I show below a better way to make sure all the jobs are completed.
for (int i = 0; i < arrScrapeboxItems.Count; i++)
{
pool.WaitOne();
ScrapeBoxItems sbi = (ScrapeBoxItems)arrScrapeboxItems[i];
wb = new Gecko.GeckoWebBrowser();
PoolObjects po = new PoolObjects();
po.link = sbi.link;
// more initialization of po ...
// and then start the thread
Thread t = new Thread(ScrapeThreadProc);
t.Start(po);
}
// Here's how you wait for all of the threads to complete.
// You have your main thread (which is running here) call `WaitOne` on the semaphore 5 times:
for (int i = 0; i < 5; ++i)
{
pool.WaitOne();
}
private void ScrapeThreadProc(object o)
{
var po = (PoolObjects)o;
Scraper scraper = new Scraper();
// initialize your Scraper object
scraper.ThreadsCompleted += new Scraper.ThreadsHandler(frmMain_NextThreadItemsCompleted);
scraper.Scrape(po);
// scraping is done. Dispose of the scraper and the po.
// and then release the semaphore
pool.Release();
}
That should greatly simplify your code.
The idea behind having the main thread wait on the semaphore 5 times is pretty simple. If the main thread can acquire the semaphore 5 times without calling Release, then you know that there aren't any other jobs running.
There are other ways to do this, as well, but they would require some more involved restructuring of your code. You should look into the Task Parallel Library, specifically Parallel.ForEach, which will handle the threading for you. You can set the maximum number of concurrent threads to 5, so that you won't get too many threads going at once.
You could also do this using a producer/consumer setup with BlockingCollection or some other shared queue.
In both of those scenarios, you end up creating 5 persistent threads that cooperatively process items from the list. That is typically more efficient than creating one thread for each item.
I have a main thread which is controlling a windows form, upon pressing a button two threads are executed. One is used for recording information, the other is used for reading it. The idea behind putting these in threads is to enable the user to interact with the interface while they are executing.
Here is the creating of the two threads;
Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();
Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();
The data is simply a Data-object that stores the data that is recorded during the recording.
The problem that I am facing is that the first thread is executed fine, the second refuses to run until the first one completes. Putting a breakpoint in the second threads function, ReadData lets me know that it is only called after the first thread is done with all of its recording.
I have been trying to solve this for a few hours now and I can't get my head around why it would do this. Adding a;
while(readThread.IsAlive) { }
right after the start will halt the execution of anything after that, and it's state is Running. But it will not go to the given method.
Any ideas?
Edit:
The two functions that are called upon by the threads are;
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
d.AddData(data);
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
double[] data = d.ReadLastData();
this.Invoke(updateData, new object[] { data });
i++;
}
}
The data object has locking in both the functions that are called upon; ReadLastData and Read.
Here are the methods in the Data object.
public void AddData(double[] data)
{
lock (this)
{
int i = 0;
foreach (double d in data)
{
movementData[i].Add(d);
i++;
}
}
}
public double[] ReadLastData()
{
double[] data = new double[channels];
lock (this)
{
int i = 0;
foreach (List<double> list in movementData)
{
data[i] = list[list.Count - 1];
}
}
return data;
}
Looks like you have a race condition between your reading/writing. In your first thread you lock down the object whilst you add data to it and in the second thread you attempt to get an exclusive lock on it to start reading. However, the problem is the first thread is executing so fast that the second thread never really gets a chance to acquire the lock.
The solution to this problem really depends on what sort of behaviour you are after here. If you expect after every write you get a consecutive read then what you need to do is control the execution between the reading/writing operations e.g.
static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens
static AutoResetEvent canRead = new AutoResetEvent(false);
...
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
canWrite.WaitOne(); // wait for the second thread to finish reading
d.AddData(data);
canRead.Set(); // let the second thread know we have finished writing
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
canRead.WaitOne(); // wait for the first thread to finish writing
double[] data = d.ReadLastData();
canWrite.Set(); // let the first thread know we have finished reading
this.Invoke(updateData, new object[] { data });
i++;
}
}
Could you try adding a Sleep inside RecordData?
Maybe it's just your (mono cpu??) windows operating system that doesn't let the second thread get its hand on cpu resources.
Don't do this:
lock (this)
Do something like this instead:
private object oLock = new object();
[...]
lock (this.oLock)
EDIT:
Could you try calls like this:
Thread recordThread = new Thread((o) => RecordData((Data)o));
recordThread.Name = "record";
recordThread.Start(data);
I am just reading a great tutorial about threads and have a problem with locks. I need some tip/advice that will point me in right direction. I'd like to understand why the output isn't ordered as i expect. The code shows my simple example.
class Program {
class A {
public object obj = new object();
public int i;
}
class B {
public object obj = new object();
public int j;
}
static void Main() {
Console.Write("Thread1: ");
A a = new A();
for (a.i = 0; a.i < 9; a.i++) {
lock (a) {
new Thread(() => { Console.Write(a.i); }).Start();
}
}
Thread.Sleep(500);
Console.Write("\nThread2: ");
B b = new B();
for (b.j = 0; b.j < 9; b.j++) {
new Thread(() => { lock (b) { Console.Write(b.j); } }).Start();
}
Console.ReadLine();
}
}
Example output:
Thread1: 222456799
Thread2: 233357889
Link to the tutorial:
http://www.albahari.com/threading/
You are only locking while you create the thread, or (in the second case), access the value. Locks must be used by all threads, otherwise they do nothing. It is the act of trying to acquire the lock that blocks. Even if you did lock in both threads, that wouldn't help you marry each thread to the value of a.i (etc) at a particular point in time (that no longer exists).
Equally, threads work at their own pace; you cannot guarantee order unless you have a single worker and queue; or you implement your own re-ordering.
it will run at its own pace, and since you are capturing the variable a, it is entirely likely that the field a.i has changed by the time the thread gets as far as Console.Write. Instead, you should capture the value, by making a copy:
A a = new A();
for (a.i = 0; a.i < 9; a.i++) {
var tmp = a.i;
new Thread(() => { Console.Write(tmp); }).Start();
}
(or probably remove a completely)
for (int i = 0; i < 9; i++) {
var tmp = i;
new Thread(() => { Console.Write(tmp); }).Start();
}
there are several issues here:
First, you are locking on a when you create a thread, so the thread is created, but your original main thread then releases the lock and keeps on trucking in the loop, while the created threads run concurrently.
You want to move the first lock into the thread that uses A to the Thread delegate like this:
for(a.i=0;a.i<9;a.i++)
{
int id=a.i;
new Thread(()=>{ lock(a){Console.Out.WriteLine("Thread{0} sees{1}",id,a.i)};}).Start(); // lots of smileys here :)
}
If you look closely, you will notice that the threads are not locked the same way for A and B, which tells you that threads live their own lives and Thread creation != Thread life.
Even with locking your thread runners, you can and will end-up in situations where thread 1 runs AFTER thread 2... but they will never run at the same time thanks to your lock.
You also reference a shared member in all your threads: a.i. This member is initialized in the main thread which doesn't lock anything so your behaviour is not predictable. This is why I added the captured variable i that grabs the value of a.i when the thread is created, and is used in the thread delegate in a safe way.
Also, always lock on a non-public instance. if you lock on A, make sure no-one sees A and gets the opportunity to lock on it.
Because the lock is always held by the main thread, as you are starting threads after acquiring lock and once you acquire there is no contention. Now the threads are free to run however they want, the threads which started by main thread aren't synchronized by any lock. Something which comes close to your expections is following (only order) count again depends on how fast and how many cores you've got. Observe b.j++ is now inside a lock.
for (b.j = 0; b.j < 9; )
{
new Thread(() => { lock (b) { Console.Write(b.j); b.j++; } }).Start();
}
Basic idea behind locking or critical section is to only allow one thing to happen, not the order, in the above modification I've locked the increment operation, that gaurantees that before next thread starts running code under lock, current thread has to finish running all the code under its acquired lock, before it releases the lock.