How to know if EventWaitHandle.Set was invoked - c#

Is there a way to know which EventWaitHandle was invoked.
i have two custom class with 2 different System Wide Event names.
The reason I had them is to distinguish which function to trigger.
The problem I have right now is how can I distinguish which event was triggered?
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
So if _ew1.Set() is invoked then I need to execute Process1.
If _ew2.Set() is invoked then I need to execute Process2.
Update: Added More Info.
the main thread is a windows service. which is signaled by a web application and a desktop application. so basically the service needs to identify who triggered the event either from a web application or a desktop application if it's a WebAppliation then Execute SP1 else if it's a Windows Application then Execute SP2.

Idea 1
WaitHandle.WaitAny static method returns index of signaled wait handle, so the simplest solution would be to check that index.
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
var handleIndex = WaitHandle.WaitAny(_eventHandles);
Console.WriteLine(handleIndex == 0 ? "Process1" : "Process2");
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
}
Idea 2
You can also use one event handle along with a volatile field that will indicate what conditional statement has been met in order to execute appropriate process after signal.
Example
enum Process
{
Process1,
Process2
}
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent _eventHandle = new AutoResetEvent(false);
private static volatile Process _selectedProcess = Process.Process1;
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
_eventHandle.WaitOne();
Console.WriteLine(_selectedProcess == Process.Process1 ? "Process1" : "Process2");
}
}
static void Method()
{
_selectedProcess = _random.Next()%2 == 0 ? Process.Process1 : Process.Process2;
_eventHandle.Set();
}
}
Idea 3
If you are unable to modify external components and you have only event handles, then you may try start new threads for each option and wait there for respective signal in order to perform appropriate operation.
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] processThreads = new Thread[2];
processThreads[0] = new Thread(Process1);
processThreads[0].Start();
processThreads[1] = new Thread(Process2);
processThreads[1].Start();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1()
{
while (true)
{
_eventHandles[0].WaitOne();
Console.WriteLine("Process1");
}
}
static void Process2()
{
while (true)
{
_eventHandles[1].WaitOne();
Console.WriteLine("Process2");
}
}
}
Idea 4
If processes require small amount of time, you can use ThreadPool.RegisterWaitForSingleObject Method
Example
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
ThreadPool.RegisterWaitForSingleObject(_eventHandles[0], Process1, null, Timeout.Infinite, false);
ThreadPool.RegisterWaitForSingleObject(_eventHandles[1], Process2, null, Timeout.Infinite, false);
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1(object state, bool timedOut)
{
Console.WriteLine("Process1");
}
static void Process2(object state, bool timedOut)
{
Console.WriteLine("Process2");
}
}

Use WaitHandle.WaitAny to wait on multiple event handles. When one or more of the events is set it'll return the index of the event that caused the wait to return.
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
WaitHandle[] handles={_ew1, _ew2};
int index=WaitHandle.WaitAny(handles)
if(index==0)
{
// mode 1
}
else if(index==1)
{
// mode 2
}

An IDEA I can suggests is to create your own EventWaitHandler, that can reuse the name of handler, later this name should be returned from the Wait method and works as an identifier of caller
for this you have to implement your own Wait method (i implemented WaitNew to cater and extend WaitOne)
See the following code for working code:
//Client application environments
public class WindowsApplication
{
public void ExecuteWindowsService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WindowsApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
public class WebApplication
{
public void ExecuteWebService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WebApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
//Windows Service Environment
public class MyEventWaitHandler : EventWaitHandle
{
public MyEventWaitHandler(bool initialState, EventResetMode mode, string name)
: base(initialState, mode, name)
{
this.EventHandlerName = name;
}
//it should not be set to empty string from external
public string EventHandlerName;
public string WaitNew()
{
if (base.WaitOne())
return EventHandlerName;
else return String.Empty;
}
}
public class WindowsService
{
public void Execute(MyEventWaitHandler _eventHandle)
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
string name = _eventHandle.WaitNew();
if (name == "WindowsApplicationMode")
{
//Execute case for first process
}
else if (name == "WebApplicationMode")
{
//Execute case for second process
}
}
}
static void Method()
{
//Some Task
}
}
Let me know if I understand your requirement correct?

Inherit from EventWaitHandle, add a volatile "Caller" property. Every signaller must pass his ID, or Ref.
After Signalled, Interlock check the property.

How about this?
bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);

Related

What happens when I reassign a frequently accessed class field to a new object?

I have a class like this:
class Test {
const int capacity = 100_0000;
private HashSet<int> set = new HashSet<int>(capacity);
public Test() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
set = new HashSet<int>(capacity);
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
set.Add(val);
}
}
The add method is frequently called.
var test = new Test();
Task.Run(() => {
for (int i = 0; i < 100000000; i++) {
test.Add(i);
Thread.SpinWait(5000);
}
});
It doesn't matter whether the data is successfully stored in the set, in this case, is the behavior of the add method consistent with the following code?
class LockTest {
const int capacity = 100_0000;
private HashSet<int> set = new HashSet<int>(capacity);
public LockTest() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
lock (set) set = new HashSet<int>(capacity);
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
lock (set) set.Add(val);
}
}
In my tests, even if there is no lock statement, there is no error. But I don't know what happens at the moment of set = new HashSet<int>(capacity);.
If you change the code to this, what do you think will happen? My guess is that the number you print out will sometimes be the same and other time different. When it is the same, lock(set) has worked, but otherwise it hasn't.
class LockTest {
const int capacity = 100_0000;
private int setCnt = 0;
private object set = new object();
public LockTest() { this.Reassign(); }
private void Reassign() {
var thread = new Thread(() => {
while (true) {
lock (set) setCnt++;
Thread.Sleep(10);
}
});
thread.Start();
}
public void Add(int val) {
lock (set) Console.WriteLine($"{setCnt}");
}
}

Multithreading sharing counter and List collection variables

Scenario, I am having multiple threads trying to sharing a static global variable counter.
After which I would add it into a List of integers and this list would be used in another thread to check out some details.
I realized after even using LOCK on the global variable counter, I still get duplicate numbers
Please pardon my explanation, codes would speak more.
Problem would be different threads may be generated a same counter value( which I don't want).
I want a running number without duplicates
class Test
{
private Object _thisLock = new Object();
List<int> listing = new List<int>(); //shared LIST
public void Main()
{
//array of threads
for (int i = 0; i < 8; i++)
{
Thread th = new Thread(Work);
th.Name = "Thread" + i;
th.Start();
}
Thread.Sleep(5000);
//Start checking for duplicates
Thread checker = new Thread(Checker);
checker.Start();
}
private void Work()
{
Object _thisLock = new Object();
while (true)
{
int a = Singleton.Instance.Counter++;
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine("WOrk : " + a);
lock (_thisLock)
{
listing.Add(a);
}
Thread.Sleep(1000);
}
}
private void Checker()
{
Object _thisLock = new Object();
while (true)
{
lock (_thisLock)
{
List<int> selflist = new List<int>();
selflist.AddRange(listing); ;
foreach (int p in selflist)
{
if (selflist.FindAll(item => item.Equals(p)).Count() > 1)
{
Console.WriteLine("Check!!!!!!!!!!!!!!!!!! : " + p);
}
}
}
Thread.Sleep(5000);
}
}
}
static void Main()
{
Test t = new Test();
t.Main();
}
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private readonly Object _thisLock = new Object();
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
private volatile static int _counter;
public int Counter
{
get
{
lock (_thisLock)
{
return _counter;
}
}
set
{
lock (_thisLock)
{
_counter = value;
}
}
}
}
In your Work method every thread have it's own lock object _thisLock.
Remove this statement in your work method and let it use private lockobject of the class:
Object _thisLock = new Object();
Why not just move the counter into the lock and make the lock shared by moving it to the class level?
private object _thisLock = new object();
...
lock (_thisLock)
{
int a = Singleton.Instance.Counter++;
listing.Add(a);
}
Also, use a thread safe collection type, like ConcurrentBag.

refreshing UI elements in work threads

Question 1: I want to refresh a label by a work thread by delegate and invoke. It works well until i try to close the form. In closing event, I stop the work thread and then the UI thread while an exception occurs(Object disposed exception). It seems that form1 is disposed. I don't know what's wrong.
Question 2: When running this code, the memory usage keep increasing. I don't think it should take so much memory space. You can see find this by checking the task manager.
here's my code:
(.Net Framework 4, winforms)
Scheduler:
class Scheduler
{
private Thread[] workThreads = null;
//Scheduler started flag
public static bool bSchedulerStarted = false;
//Work threads stop event
public static EventWaitHandle stopWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private static Scheduler self = null;
public static Scheduler getInstance()
{
if (self == null)
{
self = new Scheduler();
}
return self;
}
private Scheduler()
{
workThreads = new Thread[1];
}
private void CreateThread()
{
workThreads[0] = new Thread(Worker.doWork);
workThreads[0].IsBackground = true;
}
public void startUp()
{
if (!bSchedulerStarted)
{
stopWaitHandle.Reset();
CreateThread();
//Start all work threads
for (int i = 0; i < 1; i++)
{
workThreads[i].Start();
}
bSchedulerStarted = true;
}
}
public void stop()
{
if (!bSchedulerStarted)
return;
//Send stop event
stopWaitHandle.Set();
bSchedulerStarted = false;
if (workThreads != null)
{
//wait for all work threads to stop
for (int i = 0; i <1; i++)
{
if (workThreads[i] != null && workThreads[i].IsAlive)
workThreads[i].Join();
}
}
}
}
Worker:
class Worker
{
public static void doWork()
{
while (true)
{
if (Scheduler.stopWaitHandle.WaitOne(10, false) == true)
{
break;
}
Form1.count++;
Form1.sysMsgEvent.Set();
Thread.Sleep(10);
}
}
}
And form:
public partial class Form1 : Form
{
public static int count = 0;
public static EventWaitHandle sysMsgEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
public static EventWaitHandle stopEvent = new EventWaitHandle(false, EventResetMode.ManualReset);
private EventWaitHandle[] waitEvent = null;
Thread UIThread = null;
private delegate void ShowMsg();
public Form1()
{
InitializeComponent();
waitEvent = new EventWaitHandle[2];
waitEvent[0] = stopEvent;
waitEvent[1] = sysMsgEvent;
}
public void UpdateUI()
{
while (true)
{
switch (EventWaitHandle.WaitAny(waitEvent))
{
case 0: //Stop UI thread
return;
case 1: //Refresh UI elements
updateLabel();
break;
default:
return;
}//switch
}//while
}
private void updateLabel()
{
if (label1.InvokeRequired)
{
ShowMsg d = new ShowMsg(updateLabel);
this.Invoke(d, null);
}
else
{
label1.Text = count.ToString();
}
}
private void Form1_Load(object sender, EventArgs e)
{
UIThread = new Thread(new ThreadStart(UpdateUI));
UIThread.Start();
Scheduler sc = Scheduler.getInstance();
sc.startUp();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Scheduler sc = Scheduler.getInstance();
sc.stop();
//stop UI thread
Form1.stopEvent.Set();
}
}

Waiting for a 3rd party thread to finish

I need to call a 3rd party code that optionally starts a new thread, performs some processing, and then calls a different method on my object. What I need is wait for the 3rd party processing to be finished, then return from the original method. In other words, I have a class like this (C#):
class MyClass: IThirdPartyInterface {
void MyMethod() {
//some preprocessing
//call a 3rd party static method
ThirdParty.DoSomething(this);
}
void FinishedProcessing() {
//some postprocessing
//???
}
}
I want to modify MyMethod so that it return only after the thread that started in DoSomething has finished its execution and called the FinishedProcessing method. Since the thread is started by the third party code, I don't have access to it, so I cannot use Thread.Join here. So, what do I do instead?
You need to use an System.Threading.AutoResetEvent, it would be like this:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
}
void FinishedProcessing() {
_event.Set();
}
}
If the thread continues running after your FinishedProcessing method is called by the 3rdparty class, it would be a little diferent:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
Thread _thread;
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
_thread.Join();
}
void FinishedProcessing() {
_thread = Thread.CurrentThread;
_event.Set();
}
}
Make your MyMethod() async and then run thirdparty method inside your custom await method, moething like this:
private async void MyMethod()
{
var result = await WaitAsynchronouslyAsync();
}
public async Task<string> WaitAsynchronouslyAsync()
{
await ThirdParty.DoSomething(this);
return "Finished";
}
If ThirdParty.DoSomething does not support async pattern
you can use additional proxy with finalizer.
But it could affect application performance like a "while(myBoolFlag){}".
class Program
{
static void Main(string[] args)
{
var list = new List<ManualResetEvent>();
for (var i = 0; i < 10000; i++)
{
var m = new ManualResetEvent(false);
list.Add(m);
new Thread(Start).Start(m);
if (i > 0 && (i % 10) == 0)
for (int j = i - 10; j < i; j++)
{
list[j].WaitOne(1000);// wait signal
GC.Collect(); //force finalizer
A.Print();
}
}
}
private static void Start(object obj)
{
new A(obj as ManualResetEvent, null);
}
}
public class A : IThirdPartyInterface
{
public static long time1;
public static long count1;
private DateTime start = DateTime.Now;
private ManualResetEvent _stop;
private IThirdPartyInterface _origin;
public A(ManualResetEvent stop, IThirdPartyInterface origin)
{
_stop = stop;
_origin = origin;
}
~A()
{
Interlocked.Increment(ref count1);
Interlocked.Add(ref time1, (long)(DateTime.Now - start).TotalMilliseconds);
_stop.Set(); //send signal
}
public static void Print()
{
Console.Write("\r" + A.time1 + "\\" + A.count1 + " ");
if (A.count1 != 0)
Console.Write((A.time1 / A.count1).ToString());
}
}

Thread Pooling help

Having some issue with Threadpooling here that I need some help with please. I am trying to write a Generator, and I need to allow users generate up to 10,000 lines with the code below. Problem with this is the line
WaitHandle.WaitAll(doneEvents);
Can only handle 64 WaitAll at a time, How can I best apply thread pooling to my code in this case?
public void GenerateInsertStatements(int iRequiredRows)
{
// One event is used for each row object
ManualResetEvent[] doneEvents = new ManualResetEvent[iRequiredRows];
Row[] rows = new Row[iRequiredRows];
for (int i = 0; i < iRequiredRows; i++)
{
doneEvents[i] = new ManualResetEvent(false);
Row row = new Row(this.Name, this.TableColumns, doneEvents[i]);
rows[i] = row;
ThreadPool.QueueUserWorkItem(row.ThreadPoolCallback, i);
}
WaitHandle.WaitAll(doneEvents);
using (sr = new StreamWriter(this.Name + ".sql"))
{
for(int i=0; i<rows.Length; i++)
{
WriteStatementToFile(i, rows[i].GeneratedInsertStatement);
}
}
}
Thanks in advance
I would use just one WaitHandle and one int. Like:
int done_when_zero; // This is a field of the class
ManualResetEvent evt = new ManualResetEvent (false); // Field
...
done_when_zero = iRequiredRows; // This goes before the loop
...
evt.WaitOne (); // this goes after the loop
evt.Reset (); // Prepare for next execution if needed
And then, at the end of ThreadPoolCallback:
if (Interlocked.Decrement (ref done_when_zero)) <= 0)
evt.Set ();
As it was already suggested using a counter and a single ManualResetEvent should work fine for you. Below is ThreadPoolWait class taken from .NET Matters: ThreadPoolWait and HandleLeakTracer (see Figure 3 Better Implementation of ThreadPoolWait for more info)
public class ThreadPoolWait : IDisposable
{
private int _remainingWorkItems = 1;
private ManualResetEvent _done = new ManualResetEvent(false);
public void QueueUserWorkItem(WaitCallback callback)
{
QueueUserWorkItem(callback, null);
}
public void QueueUserWorkItem(WaitCallback callback, object state)
{
ThrowIfDisposed();
QueuedCallback qc = new QueuedCallback();
qc.Callback = callback;
qc.State = state;
lock (_done) _remainingWorkItems++;
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleWorkItem), qc);
}
public bool WaitOne() { return WaitOne(-1, false); }
public bool WaitOne(TimeSpan timeout, bool exitContext)
{
return WaitOne((int)timeout.TotalMilliseconds, exitContext);
}
public bool WaitOne(int millisecondsTimeout, bool exitContext)
{
ThrowIfDisposed();
DoneWorkItem();
bool rv = _done.WaitOne(millisecondsTimeout, exitContext);
lock (_done)
{
if (rv)
{
_remainingWorkItems = 1;
_done.Reset();
}
else _remainingWorkItems++;
}
return rv;
}
private void HandleWorkItem(object state)
{
QueuedCallback qc = (QueuedCallback)state;
try { qc.Callback(qc.State); }
finally { DoneWorkItem(); }
}
private void DoneWorkItem()
{
lock (_done)
{
--_remainingWorkItems;
if (_remainingWorkItems == 0) _done.Set();
}
}
private class QueuedCallback
{
public WaitCallback Callback;
public object State;
}
private void ThrowIfDisposed()
{
if (_done == null) throw new ObjectDisposedException(GetType().Name);
}
public void Dispose()
{
if (_done != null)
{
((IDisposable)_done).Dispose();
_done = null;
}
}
}
Probably not the most efficient solution, but it should work regardless of the 64 wait handles limit :
for(int i = 0; i < iRequiredRows; i++)
doneEvents[i].WaitOne();

Categories