Multiple threads modifying a collection - multithreading

I'm trying to learn about threads for an assignment for school, and I'm trying to get two threads to empty a collection. The code I came up with so far throws an exception, saying that the collection got modified.
First I had a while loop in the locked code part, but then (of course ;-)) only one thread empties the collection.
My question is, how can I have a loop in which the threads both take turns in emptying the collection?
class Program
{
private static List<int> containers = new List<int>();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
containers.Add(i);
}
Thread t1 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });
t1.Name = "Kraan 1";
t1.Start();
Thread t2 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });
t2.Name = "Kraan 2";
t2.Start();
Console.Write("Press any key to continue...");
Console.Read();
}
static void GeefContainer()
{
lock (containers)
{
int containerNummer = containers.Count - 1;
//Container container = containers[containerNummer];
//Console.Write("Container {0} opgehaald... Overladen", containerNummer);
Console.WriteLine("Schip: Container {0} gegeven aan {1}", containerNummer, Thread.CurrentThread.Name);
//Gevaarlijk, want methode aanroepen kan klappen
containers.RemoveAt(containerNummer);
}
}
}

I assume you are not allowed to use any of the ThreadSafe collections found in the System.Collections.Concurrent namespace.
You need to gain exclusive access to the containers collection when checking if there are still entries left. Yet, you don't want 1 thread to take exclusive control removing all entries before releasing its lock. Monitor.Pulse can be used to allow other threads waiting to lock the container to 'go first'. Try the following implementation of GeefContainers:
static void GeefContainer()
{
lock (containers)
{
while (containers.Any()) // using linq, similar to: while(container.Count > 0)
{
containers.RemoveAt(0); // remove the first element
// allow other threads to take control
Monitor.Pulse(containers); // http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse.aspx
// Wait for a pulse from the other thread
Monitor.Wait(container);
}
}
}
Oh, and remove your looping logic from:
Thread t2 = new Thread(() => { foreach (int container in containers) { GeefContainer(); } });
Simply invoking GeefContainer is enough.
This can be visualized in the following way:
Thread 1 gains a lock to 'collections'
Thread 2 is blocked since it's waiting for an exclusive lock to 'collections'
Thread 1 removes an entry from 'collections'
Thread 1 releases it's lock on 'collections' and tries to gain a new exclusive lock
Thread 2 gains a lock to 'collections'
Thread 2 removes an entry from 'collections'
Thread 2 releases it's lock on 'collections' and tries to gain a new exclusive lock
Thread 1 gains a lock to 'collections'
etc

The exception you are seeing is being thrown by the enumerator. Enumerators on standard collections have checks to make sure the collection was not modified in the middle of an enumeration operation (via foreach in your case).
Since you want to have your threads alternate removing from the collection then you will need some kind of mechanism that allows the threads to signal each other. We also have to be careful not to access the collection from multiple collections at the same time. Not even the Count property is safe to use without synchronization. The Barrier class makes the signaling really easy. A simple lock will suffice for the synchronization. Here is how I would do this.
public class Program
{
public static void Main(string[] args)
{
var containers = new List<int>();
for (int i = 0; i < 100; i++)
{
containers.Add(i);
}
var barrier = new Barrier(0);
var t1 = new Thread(() => GeefContainers(containers, barrier));
t1.Name = "Thread 1";
t1.Start();
var t2 = new Thread(() => GeefContainers(containers, barrier));
t2.Name = "Thread 2";
t2.Start();
Console.Write("Press any key to continue...");
Console.Read();
}
private static void GeefContainers(List<int> list, Barrier barrier)
{
barrier.AddParticipant();
while (true)
{
lock (list)
{
if (list.Count > 0)
{
list.RemoveAt(0);
Console.WriteLine(Thread.CurrentThread.Name + ": Count = " + list.Count.ToString());
}
else
{
break;
}
}
barrier.SignalAndWait();
}
barrier.RemoveParticipant();
}
}
The Barrier class basically causes this to happen over and over again.
|----| |----| |----|
| T1 |-->| |-->| T1 |-->| |-->| T1 |
|----| | | |----| | | |----|
|-->(B)-->| |-->(B)-->|
|----| | | |----| | | |----|
| T2 |-->| |-->| T2 |-->| |-->| T2 |
|----| |----| |----|
In the above diagram T1 and T2 represent the remove operations on threads 1 and 2 respectively. (B) represents a call to Barrier.SignalAndWait.

First, change your thred definition as follows:
new Thread(() => { while(containers.Count>0) { GeefContainer(); } });
Then, rewrite GeefContainer() as follows to avoid exceptions:
static void GeefContainer()
{
lock (containers)
{
int containerNummer = containers.Count - 1;
if(containerNummer>=0)
{
//Container container = containers[containerNummer];
//Console.Write("Container {0} opgehaald... Overladen", containerNummer);
Console.WriteLine("Schip: Container {0} gegeven aan {1}", containerNummer, Thread.CurrentThread.Name);
//Gevaarlijk, want methode aanroepen kan klappen
containers.RemoveAt(containerNummer);
}
}
}

What if you modify your threads as follows? That way, both threads should get some time to perform actions on the collection.
Thread t1 = new Thread(() => {
while (containers.Count > 0)
{
GeefContainer();
Thread.Sleep(150);
}});
t1.Name = "Kraan 1";
t1.Start();
Thread t2 = new Thread(() => {
while (containers.Count > 0)
{
GeefContainer();
Thread.Sleep(130);
}});
t2.Name = "Kraan 2";
t2.Start();

Related

Getting value from thread running in while loop

I have a java thread which is running a path-finding algorithm in a constant while loop. Then, every so often I want to retrieve the most updated path from the thread. However, I am unsure how to do this, and think I might be doing it wrong.
My thread consists of the following code:
public class BotThread extends Thread {
Bot bot;
AStar pathFinder;
Player targetPlayer;
public List<boolean[]> plan;
public BotThread(Bot bot) {
this.bot = bot;
this.plan = new ArrayList<>();
pathFinder = new AStar(bot, bot.getLevelHandler());
}
public void run() {
while (true) {
System.out.println("THREAD RUNNING");
targetPlayer = bot.targetPlayer;
plan = pathFinder.optimise(targetPlayer);
}
}
public boolean[] getNextAction() {
return plan.remove(0);
}
}
I then create an object of BotThread, and call start(). Then when I call getNextAction() on the thread, I seem to receive a null pointer. Is this because I am not able to call another method on the thread whilst it is in the main loop? How should I do this properly?
This is because you are not giving enough time to thread to initialise plan Arraylist. You need to add sleeping time to the threads. Something like this while calling BotThread class from main:
int num_threads = 8;
BotThread myt[] = new BotThread[num_threads];
for (int i = 0; i < num_threads; ++i) {
myt[i] = new BotThread();
myt[i].start();
Thread.sleep(1000);
myt[i].getNextAction();
}

How to distribute the operations on a single thread to different multiple threads

How can I distribute the operations, say duplicate the items\actions sent in one pipe to various different pipes which can access the original pipe?
Say I have Parent thread is "Pthread", I want to link it to 4 or 5 child threads, Just like a binary tree. Any operations performed on "Pthread" should be distributed to all the child threads(Something similar to what ESB does in the SOA architecture).
Like A+B should be sent in all the 5 threads\pipes at the same time and processed.
Is there a way to do this?
public class MainThreadEntry {
public void ThreadCreationMethod()
{
List<Future<Object>> listOfResult = null; // listOfResult is list of Integer objects as a result of computation by different threads
ExecutorService executor = Executors.newFixedThreadPool(5); // no of threads to create from main thread
List<EachThreadComputation> list = new ArrayList<MainThreadEntry .EachThreadComputation>();
for (int i = 0; i < 5; i++) {
EachThreadComputation separeateComputaionInnerClass = new EachThreadComputation(1,2); // innerClass Created For Ecah Thread 1,2 parameter can be dynamic
list.add(separeateComputaionInnerClass);
}
try {
listOfResult = executor.invokeAll(list); // call on different threads with 5 separate executionpath for computation
} catch (InterruptedException e) {
}
}
private class EachThreadComputation implements Callable<Object>{
private int A;
private int B;
EachThreadComputation(int A,int B) {
this.A = A;
this.B = B;
}
#Override
public Object call() throws Exception {
return (Integer)A+B
}
}}

CyclicBarrier code not working?

I got CyclicBarrier code from oracle page to understand it more. I modified it and now having one doubt.
Below code doesn't terminate but If I uncomment Thread.sleep condition, It works fine.
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class Solver {
final int N;
final float[][] data;
boolean done = false;
final CyclicBarrier barrier;
class Worker implements Runnable {
int myRow;
Worker(int row) {
myRow = row;
}
public void run() {
while (!done) {
processRow(myRow);
try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
System.out.println("Run finish for " + Thread.currentThread().getName());
}
private void processRow(int row) {
float[] rowData = data[row];
for (int i = 0; i < rowData.length; i++) {
rowData[i] = 1;
}
/*try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
done = true;
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N, new Runnable() {
public void run() {
for (int i = 0; i < data.length; i++) {
System.out.println("Data " + Arrays.toString(data[i]));
}
System.out.println("Completed:");
}
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i), "Thread "+ i).start();
}
}
public class CyclicBarrierTest {
public static void main(String[] args) {
float[][] matrix = new float[5][5];
Solver solver = new Solver(matrix);
}
}
Why Thread.sleep is required in above code?
I've not run your code but there may be a race condition, here is a scenario that reveals it:
you start the first thread, it runs during a certain amount of time sufficient for it to finish the processRow method call so it sets done to true and then waits on the barrier,
the other threads start but they see that all is "done" so they don't enter the loop and they'll never wait on the barrier, and end directly
the barrier will never be activated as only one of the N threads has reached it
deadlock
Why it is working with the sleep:
when one of the thread starts to sleep it lets the other threads work before marking the work as "done"
the other threads have enough time to work and can themselves reach the barrier
2 seconds is largely enough for 5 threads to end a processing that should not last longer than 10ms
But note that if your system is ovrerloaded it could too deadlock:
the first thread starts to sleep
the OS scheduler lets another application work during more than 2 seconds
the OS scheduler comes back to your application and the threads scheduler chooses the first thread again and lets it terminate, setting done to true
and here again the first scenario => deadlock too
And a possible solution (sorry not tested):
change your while loops for do/while loops:
do
{
processRow(myRow);
...
}
while (!done);

Error Cross-thread operation not valid: Control 'CameraViewVS' accessed from a thread other than the thread it was created on. parallel.for

I have a timer to verify one condition every time and show pop up form only once if the condition is verified. I want to verify in parallel all instances, so i used parallel.for, but i have this error "Cross-thread operation not valid: Control 'CameraViewVS' accessed from a thread other than the thread it was created on." in line " frm.WindowState = FormWindowState.Normal;"
this is my code:
public void timer1_Tick(object source, EventArgs e)
{
Parallel.For(0, nbre, l =>
{
cameraInstanceList[l].Start();
if (cameraInstanceList[l].MoveDetection == true)
{
//show the the form S once
foreach (Form S in Application.OpenForms)
{
var frm = S as Formes.CameraViewVS;
if (frm != null && frm.IP == cameraInstanceList[l].adresse)
{
cameraInstanceList[l].MoveDetection = false;
frm.WindowState = FormWindowState.Normal;
frm.Activate();
return;
}
}
f1 = new Formes.CameraViewVS(cameraInstanceList[l],
adresseIPArray[l]);
f1.Show(this);
}
}
);
Most properties on WinForm object instances need to be accessed from the thread that they were created on. You can use the Control.InvokeRequired property to determine if you need to use the control (or form) Invoke method to execute the code on the UI thread.
It is also a good practise to create most WinForm controls on the main UI thread, and not on any thread pool threads. In WinForms applications, you can use the SynchronizationContext to ensure some code, such as creating a form, is called on the UI thread.
EDIT: changed so that the method doesn't return after movement detected.
public void timer1_Tick(object source, EventArgs e)
{
// assume this is being called on the UI thread, and save the thread synchronization context
var uiContext = SynchronizationContext.Current;
Parallel.For(0, nbre, l =>
{
while (true)
{
Thread.Sleep(250); // <--- sleep for 250 ms to avoid "busy" wait
cameraInstanceList[l].Start();
if (cameraInstanceList[l].MoveDetection == true)
{
// capture instances used in closures below
var cameraInstance = cameraInstanceList[l];
var ipAdresse = adresseIPArray[l];
//show the the form S once
foreach (Form S in Application.OpenForms)
{
var frm = S as Formes.CameraViewVS;
if (frm != null)
{
// create delegate to be invoked on form's UI thread.
var action = new Action(() =>
{
if (frm.IP == cameraInstance.adresse)
{
cameraInstance.MoveDetection = false;
frm.WindowState = FormWindowState.Normal;
frm.Activate();
}
};
if (frm.InvokeRequired)
frm.Invoke(action);
else
action();
continue; // <--- go back to the top of the while loop
// and wait for next detection
}
}
// create delegate to create new form on UI thread.
var createNewFormCallback = new SendOrPostCallback((o) =>
{
f1 = new Formes.CameraViewVS(cameraInstance, ipAdresse);
f1.Show(this);
};
// and invoke the delegate on the ui thread
uiContext.Send(createNewFormCallback, null);
}
}
}
);
}
Thomas is very close to right answer ,Because Every Control runs in a different thread .You should just write a code for context-switching of resources which is being used by Controls
Thread ..Don't worry you have a lot of facility for this in c sharp.Just use BeginInvoke and Invoke and i hope you would be able to resolve your problem.Write this in place of your old code block ..
var action = new Action(() =>
{
if (frm.IP == cameraInstance.adresse)
{
cameraInstance.MoveDetection = false;
frm.WindowState = FormWindowState.Normal;
frm.Activate();
}
};
if (frm.InvokeRequired)
frm.BeginInvoke(action);
else
frm.Invoke(action);

spawn multiple threads in loop and knowing when all finished to do certain task

I have to spawn multiple threads in loop for configured no. of sites and then each thread has multiple child threads. After finishing all threads I need to do certain task to save data into database. How I come to know whether all task has finished.
my current code:
List<SocialDataConfig> configList = SetConfiguration();
foreach (SocialDataConfig config in configList)
{
new Thread(delegate()
{
FetchSocialData(config);
}).Start();
}
// save fetched data into database and log fetched information in database
private void FetchSocialData(SocialDataConfig config)
{
for (int i = 0; i < config.ThreadCount; i++)
{
Thread thread = new Thread(delegate()
{
FetchData(54764876, config);
});
thread.Start();
}
}
Instead of creating your own threads you can use the new Task library in C#.
You can then use something like this:
int n = 10;
// Construct started tasks
Task<int>[] tasks = new Task<int>[n];
for (int i = 0; i < n; i++)
{
tasks[i] = Task<int>.Factory.StartNew(action, i);
}
// Wait for all the tasks to finish.
Task.WaitAll(tasks);
Here is the MSDN documentation on WaitAll with a complete example.

Resources