.NET Threadpool synchronizing using AutoResetEvent - c#

Following is the code that I use. The main thread waits for Threadpool threads to execute. I use AutoResetEvent (WaitHandle), but I am really surprised that I am way off the mark, as the code doesn't behave as expected.
I have two concentric for loops, where Threadpool is in the inner loop and it is expected that for each iteration of the outer loop, all the inner loop values should be processed. Main thread is made to wait using AutoResetEvent WaitOne call just outside inner loop, a static variable which is reset on every iteration of the outerloop to the max value of the inner loop, and is decremented using Interlock in the method call on Threadpool thread is used to call the Set for the AutoResetEvent. However, even when I expect the static variable to show the value 0 after every inner loop, it doesn't. What is the issue in my code and what are better options for me to accomplish the task? In fact, due to the mix up of the values, the main thread doesn't really seem to be waiting for the Threadpool threads.
using System;
using System.Threading;
namespace TestThreads
{
class Program
{
private static int threadingCounter = 0;
private static readonly object lockThreads = new Object();
private AutoResetEvent areSync = new AutoResetEvent(true);
// <param name="args"></param>
static void Main(string[] args)
{
Program myProgram = new Program();
try
{
try
{
for (int outer = 0; outer < 1000; outer++)
{
threadingCounter = 500;
try
{
for (int inner = 0; inner < 500; inner++)
{
ThreadPool.QueueUserWorkItem(new
WaitCallback(myProgram.ThreadCall), inner);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
myProgram.areSync.WaitOne();
}
if(threadingCounter != 0)
Console.WriteLine("In Loop1, Thread Counter :: " +
threadingCounter);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
}
catch(Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
threadingCounter = 0;
if (myProgram.areSync != null)
{
myProgram.areSync.Dispose();
myProgram.areSync = null;
}
}
}
public void ThreadCall(object state)
{
try
{
int inner = (int)state;
Thread.Sleep(1);
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
Interlocked.Decrement(ref threadingCounter);
if (threadingCounter <= 0)
areSync.Set();
}
}
}
}

You have initialized AutoResetEvent with initial state as signaled(true) which will allow first call to
myProgram.areSync.WaitOne();
to continue without blocking, so it continues to outer loop and Queues execution to Threadpool again, hence the results are messed up. it is very clear.
update your code to
private AutoResetEvent areSync = new AutoResetEvent(false);
for expected results. hope this helps

I would refactor this using something like this. This assumes you want to do something in background threads in your inner loop, finish each of those before proceeding with your next outer loop, avoid messy exception handling while still capturing the exceptions that occurred during processing so that you can deal with those exceptions after processing is complete for both inner and outer loop.
// track exceptions that occurred in loops
class ErrorInfo
{
public Exception Error { get; set; }
public int Outer { get; set; }
public int Inner { get; set; }
}
class Program
{
static void Main(string[] args)
{
// something to store execeptions from inner thread loop
var errors = new ConcurrentBag<ErrorInfo>();
// no need to wrap a try around this simple loop
// unless you want an exception to stop the loop
for (int outer = 0; outer < 10; outer++)
{
var tasks = new Task[50];
for (int inner = 0; inner < 50; inner++)
{
var outerLocal = outer;
var innerLocal = inner;
tasks[inner] = Task.Factory.StartNew(() =>
{
try
{
Thread.Sleep(innerLocal);
if (innerLocal % 5 == 0)
{
throw new Exception("Test of " + innerLocal);
}
}
catch (Exception e)
{
errors.Add(new ErrorInfo
{
Error = e,
Inner = innerLocal,
Outer = outerLocal
});
}
});
}
Task.WaitAll(tasks);
}
Console.WriteLine("Error bag contains {0} errors.", errors.Count);
Console.ReadLine();
}
}

Related

c# 2 events with same nameļ¼Œ got chaos at running time, how should i avoid this?

I have a method "Add2List", who creates a ManualResetEvent and stores it in SortedList of a instance, then waits for signaling, then do some work and dispose the event.
I have another method "DoSomething", who listens to remote server and then signals the stored manual events according to Guid.
in the multithreading context, multi threads calls method "Add2List", so in the sortedlist there may have several manual event with same name at the same moment. But this may cause chaos. How should i avoid this?
To be simpler, i wrote this test code:
Class Program
{
static void Main(string[] args)
{
StringBuilder str = new StringBuilder();//a string to record what happened
//test iteratively
for(int i=0;i<100;i++)
{
EventHolder holder = new EventHolder();
Signaler ob2 = new Signaler();
Thread th1 = new Thread(holder.Add2List);
Thread th2 = new Thread(holder.Add2List);
Thread th3 = new Thread(ob2.DoSomething);
th1.Start(1);
th2.Start(2);
th3.Start();
//Make sure all thread is ended before the next iteration.
while(th1.IsAlive){ Thread.Sleep(200); }
while(th2.IsAlive){ Thread.Sleep(200); }
while(th3.IsAlive){ Thread.Sleep(200); }
}
Console.Read();
}
public class EventHolder
{
static SortedList<int, ManualResetEvent> MyManualEventList = new SortedList<int, ManualResetEvent>();
public EventHolder()
{
MyManualEventList = new SortedList<int, ManualResetEvent>();
Signaler.SignalMyManualEvent += OnSignalMyManualEvent;
}
void OnSignalMyManualEvent(int listindex)
{
try { MyManualEventList[listindex].Set(); }
catch(Exception e)
{
Console.WriteLine("Exception throws at " + System.DateTime.Now.ToString() +" Exception Message:"
Console.WriteLine(e.Message);
int temp = 0; //*Here is a breakpoint! To watch local variables when exception happens.
}
}
public void Add2List(object listindex)
{
ManualResetEvent MyManualEvent = new ManualResetEvent(false);
MyManualEvent.Reset();
MyManualEventList.Add((int)listindex, eve);
//in this test, this countdownevent need to be signaled twice, for it has to wait until all 2 event been added to MyManualEventList
Signaler.StartTrySignal.Signal();
MyManualEvent.WaitOne();
Console.WriteLine("Event" + ((int)listindex).ToString() + " been detected at " + System.DateTime.Now.Tostring());
MyManualEvent.Dispose();
}
}
public class Signaler
{
public delegate void Signalhandler(int listindex);
public static event Signalhandler SignalMyManualEvent;
public static CountDownEvent StartTrySignal = new CountDownEvent(2); // signaled twice so that the 2 manual events were added to sortedlist
void RaiseSignalMyManualEvent(int listindex)
{
var vr = SignalMyManualEvent;
if(vr != null)
vr(listindex);
}
int i = 0, j = 0, k = 0;
// here i use 2 prime numbers to simulate the happening of 2 random events
public Signaler()
{
StartTrySignal.Reset();
}
public void DoSomething()
{
StartTrySignal.Wait(); // wait for the 2 manual events been added to sortedlist
//To signal MyManualEventList[1] or MyManualEventList[2]
while(i + j == 0)
{
Random rnd = new Random();
k = rnd.Next();
if(k % 613 == 0) { i = 1; Console.WriteLine("Event1 Raised!"; RaiseSignalMyManualEvent(1); }
else if(k % 617 == 0) { j = 1; Console.WriteLine("Event1 Raised!"; RaiseSignalMyManualEvent(2); }
}
//if MyManualEventList[1] has not been signaled, wait something to happen, and signal it.
while(i == 0)
{
Random rnd = new Random();
k = rnd.Next();
if(k % 613 == 0)
{
i = 1;
if(j>0)
{
m++;
Console.WriteLine("All 2 Events Raised! - iteration " + m.ToString());
}
RaiseSignalMyManualEvent(1);
}
}
//if MyManualEventList[2] has not been signaled, wait something to happen, and signal it.
while(j == 0)
{
Random rnd = new Random();
k = rnd.Next();
if(k % 617 == 0)
{
j = 1;
m++;
Console.WriteLine("All 2 Events Raised! - iteration " + m.ToString());
RaiseSignalMyManualEvent(2);
}
}
}
}
public class Counter //Provide a number to record iteration
{
public static int m = 0;
}
}
Result:
Sorry for do not have enough reputation to post images.
At the line where there's a breakpoint, system throws exception " the given key is not in dictionary". this exception happens randomly, sometimes because th1 disposed <2, MyManualEvent> or th2 disposed <1, MyManualEvent> , sometimes none has been disposed but it just cannot find anyone.
I run this program 3 times, exception happens at iteration12, iteration45, and iteration0 (at the beginning).
OK 2 answers
1: Your code returns "Event 1" after "All events", because the two console.writelines are in a race condition (the last while loop is never iterated)
2: the 'System' distingushes between the two ManualResetEvent objects becuase it references the SortedList you put them in. ie.
static SortedList<int, ManualResetEvent> MyManualEventList
= new SortedList<int, ManualResetEvent>();
public EventHolder() { Signaler.SignalMyManualEvent
+= OnSignalMyManualEvent; }
void OnSignalMyManualEvent(int listindex)
{
MyManualEventList[listindex].Set();
}
when you raise event 1 you call set on Item 1 in the SortedList and when you raise Event 2 you call set on Item 2 in the list.
this is bad because the calling code has no idea which thread it is allowing to continue and you could well get a null exception

Multithread Exception handling

Here's a simple program:
class Program
{
static Calc calc = new Calc();
static void Main(string[] args)
{
try
{
var t1 = new Thread(calc.Divide);
t1.Start();
}
catch (DivideByZeroException e)
{
//Console.WriteLine("Error thread: " + e.Message);
}
try
{
calc.Divide();
}
catch (Exception e)
{
//Console.WriteLine("Error calc: " + e.Message);
}
}
class Calc
{
public int Num1;
public int Num2;
Random random = new Random();
public void Divide()
{
for (int i = 0; i < 100000; i++)
{
Num1 = random.Next(1, 10);
Num2 = random.Next(1, 10);
try
{
int result = Num1 / Num2;
}
catch (Exception ex)
{
throw ex;
}
Num1 = 0;
Num2 = 0;
}
}
}
}
Two threads are executing same method at the same time. One of them sets Num1 to 0 while the other one is trying to divide by Num1 (0) at the same time. The question is why is exception thrown, why it's not caught by try catch block inside the Main method?
Main thread is one thread and your new thread is another thread. Those two threads does not talk to each other meaning that they are totally independent. If you want to catch the exception on your main thread there are two ways of doing it
Use a backgroundworker class, the RunWorkerCompleted event will be fired on main thread, e.exception will tell you if an exception caused the thread to be aborted.
Use a global catcher
add this line before your codes
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
and
void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//handle the exception
}

Trying to cause a read or write error in multi-threading

How come the following doesn't give me a read / write error ever?
In my main thread I increment i, which is a read, and a write.
In both threads I write to total.
I would expect to see an error, but I leave it running and never get one, why is this?
For reference, my computer has 2 cores, 4 logical cores, its an Intel i3.
using System;
using System.Collections.Generic;
using System.Threading;
namespace Threading001
{
class Program
{
static void Main(string[] args)
{
int i = 0;
int total = 0;
new Thread(() => {
var service2 = new Service();
while (true)
{
try
{
total += i;
}
catch (Exception ex)
{
Console.WriteLine("Error from thread 2: {0}", ex);
break;
}
}
}).Start();
while (true)
{
try
{
total += i;
i++;
}
catch (Exception ex)
{
Console.WriteLine("Error from thread 1: {0}", ex);
break;
}
}
}
}
}
Since both threads may update total at the same time, the error you may get is a "corrupted" total. i.e.: that total doesn't contain the "correct" sum. However, it won't throw an Exception.
If you want to do this kind of things and avoid any potential error, you could use Interlocked.Add:
Interlocked.Add(ref total, i)
Here is a simplified example:
using System;
using System.Collections.Generic;
using System.Threading;
namespace Threading001
{
class Program
{
static void Main(string[] args)
{
int total = 0;
Thread thread = new Thread(() => {
for ( int j=0 ; j < 1000000 ; j++)
{
Interlocked.Add(ref total, 1);
//total++; //not thread-safe
}
});
thread.Start();
for ( int i=0 ; i < 1000000 ; i++)
{
Interlocked.Add(ref total, 1);
//total++; //not thread-safe
}
thread.Join();
Console.WriteLine(total);
}
}
}
With the version not thread safe, I get a different total each time (eg: 1425407, 1109498, ...).
With the thread safe version, I get 2000000 every time.
So, conclusion: if both threads try to write at the same time, I won't get the results I want. However, it won't throw an exception.
race condition does not throw an exception.
http://en.wikipedia.org/wiki/Race_condition
notice the Example
here is the question in a "correct" manner
pthreads: If I increment a global from two different threads, can there be sync issues?

c# pause within catch statement not working

I have a try/catch block and within catch am trying to apply a pause but no matter what method I try (pause, threadsleep) it simply continues. and ignores all pauses in the mainblock. Is this a .NET bug?
catch (Exception ex)
{
if (maxDelay < 1)
maxDelay = 1;
newpause(maxDelay);
// Pause(maxDelay * 60);
Current = "Error:" + txt;
LogUpdater.UpdateLog(f, "Error sending : " + txt + ".");
System.Threading.Thread.Sleep(10);
bw.ReportProgress(1);
}
public void newpause(int maxDelay)
{
for (int i = 0; i < 60; i++)
{
System.Threading.Thread.Sleep(maxDelay*1000);
Application.DoEvents();
}
}
Please try running following code. It works on my side.
class PauseExample
{
static void Main(string[] args)
{
int a = 90;
int b = 0;
try
{
int c = a / b;
}
catch
{
Console.WriteLine("In catch");
System.Threading.Thread.Sleep(5000); //waits for 5 seconds
Console.WriteLine("Out of catch");
}
}
}
Let me know if this helps!
Your passing one/tenth of a second.
Your only passing 10 milliseconds, 1000 would be 1 second.
System.Threading.Thread.Sleep(1000); // One Second.

C# Only One Thread Executes

I have a multithread application. I want only one thread to execute my function and other threads to pass it while my function executing. How can I do this?
My method is something like:
public void setOutput(int value)
{
try
{
GPOs gpos = reader.Config.GPO;
gpos[1].PortState = GPOs.GPO_PORT_STATE.TRUE;
gpos[2].PortState = GPOs.GPO_PORT_STATE.TRUE;
Thread.Sleep(WAIT);
gpos[1].PortState = GPOs.GPO_PORT_STATE.FALSE;
gpos[2].PortState = GPOs.GPO_PORT_STATE.FALSE;
}
catch (Exception ex)
{
logger.Error("An Exception occure while setting GPO to " + value + " " + ex.Message);
}
}
You can use a lock object in combination with Monitor.TryEnter.
private Object outputLock = new Object();
public void setOutput(int value)
{
if Monitor.TryEnter(outputLock)
{
try
{
.... your code in here
}
finally
{
Monitor.Exit(outputLock);
}
}
}
Only one thread at at time will be allowed into the Monitor.TryEnter block. If a thread arrives here while another thread is inside, then Monitor.TryEnter returns false.
You can use a Mutex
using System;
using System.Threading;
class Test
{
// Create a new Mutex. The creating thread does not own the
// Mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void MyThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area\r\n",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
}
}
the accepted answer (https://stackoverflow.com/a/10753349/1606741 as of writing) is right, but I think using https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement is clearer and does basically the same.
One thread at a time can execute the block
private object once = new object();
public void setOutput(int value)
{
lock (once)
{
try
{
GPOs gpos = reader.Config.GPO;
gpos[1].PortState = GPOs.GPO_PORT_STATE.TRUE;
gpos[2].PortState = GPOs.GPO_PORT_STATE.TRUE;
Thread.Sleep(WAIT);
gpos[1].PortState = GPOs.GPO_PORT_STATE.FALSE;
gpos[2].PortState = GPOs.GPO_PORT_STATE.FALSE;
}
catch (Exception ex)
{
logger.Error("An Exception occure while setting GPO to " + value + " " + ex.Message);
}
}
}
You can give a name to your threads and check the name in the method
What about this solution:
private AutoResetEvent are = new AutoResetEvent();
public void setOutput(int value)
{
// Do not wait (block) == wait 0ms
if(are.WaitOne(0))
{
try
{
// Put your code here
}
finally
{
are.Set()
}
}
}
It seems be easier (cheaper) than Monitor with lock object, but maybe not so clear.

Categories