Waiting on multiple different pulses events - c#

I have been given an application that boils down to being a producer-consumer pattern. Several threads are doing some work and updating a single data set so that several more threads can consume that data and do their own work with it. At the moment, it's not terribly complex, all the consuming threads wait on the data set until one of the producers calls a pulseall.
There is now a desire to have one of the consumer threads consume from two different data sets anytime either of the sets changes. The teams desire to keep refactoring to a minimum and my limited experience with threading has given me some issues finding a clean solution.
The quick and dirty solution was to do the waiting and pulsing on a separate object and have the consumer threads check for changes in their data set before continuing. There does not seem to be a way for one thread to wait on two objects, without replacing the generic threads with a more robust threading tool (thread pools, task, etc) unless I'm failing to google the right thing.

If you are willing to do a little refactoring I would recommend switching from Monitor to one of the EventWaitHandle derived classes.
Depending on the behavior you want you may want AutoResetEvent, that will more closely act like a Monitor.Entier(obj)/Monitor.Exit(obj)
private readonly object _lockobj = new Object();
public void LockResource()
{
Monitor.Enter(_lockobj);
}
public void FreeResource()
{
Monitor.Exit(_lockobj);
}
//Which is the same as
private readonly AutoResetEvent _lockobj = new AutoResetEvent(true);
public void LockResource()
{
_lockobj.WaitOne();
}
public void FreeResource()
{
_lockobj.Set();
}
or you may want ManualResetEvent will more closely act like Monitor.Wait(obj)/Monitor.PulseAll(obj)
private readonly object _lockobj = new Object();
public void LockResource()
{
Monitor.Enter(_lockobj);
}
public bool WaitForResource()
{
//requires to be inside of a lock.
//returns true if it is the lock holder.
return Monitor.Wait(_lockobj);
}
public void SignalAll()
{
Monitor.PulseAll(_lockobj);
}
// Is very close to
private readonly ManualResetEvent _lockobj = new ManualResetEvent(true);
public bool LockResource()
{
//Returns true if it was able to perform the lock.
return _lockobj.Reset();
}
public void WaitForResource()
{
//Does not require to be in a lock.
//if the _lockobj is in the signaled state this call does not block.
_lockobj.WaitOne();
}
public void SignalAll()
{
_lockobj.Set();
}
1 event can wake up multiple threads, to handle multiple events by one thread you can do
ManualResetEvent resetEvent0 = ...
ManualResetEvent resetEvent1 = ...
public int WaitForEvent()
{
int i = WaitHandle.WaitAny(new WaitHandle[] {resetEvent0, resetEvent1});
return i;
}
and i will be the index of the reset event that had Set() called on it.

Related

How to read/write from a global variable in main thread

I have a C# Windows IoT Background application I have created. That application has multiple threads in the ThreadPool that run indefinitely.
These threads need to be able to read/write to global variables in the main thread, but I am not sure how to accomplish this. Here is an example of what I am trying to do:
// main task
public sealed class StartupTask : IBackgroundTask
{
private static BackgroundTaskDeferral _Deferral = null;
private static MyThreadClass1 thread1 = null;
private static MyThreadClass2 thread2 = null;
private static MyThreadClass3 thread3 = null;
List<Object> MyDevices = null;
public async void Run(IBackgroundTaskInstance taskInstance)
{
_Deferral = taskInstance.GetDeferral();
MyDevices = GetDeviceList();
thread1 = new MyThreadClass1();
await ThreadPool.RunAsync(workItem =>
{
thread1.Start();
});
thread2 = new MyThreadClass2();
await ThreadPool.RunAsync(workItem =>
{
thread2.Start();
});
thread3 = new MyThreadClass3();
await ThreadPool.RunAsync(workItem =>
{
thread3.Start();
});
}
}
internal class MyThreadClass1
{
public async void Start()
{ }
}
internal class MyThreadClass2
{
public async void Start()
{ }
}
internal class MyThreadClass3
{
public async void Start()
{ }
}
In any of the three threads that are running, I need to be able to read and write to List<Object> MyDevices.
The threads all have different functions, but they all interact with "MyDevices", so if one thread makes a change to that list, the other threads need to know about the change right away.
What is the best way to go about doing this?
Thanks!
These threads need to be able to read/write to global variables in the main thread
The easiest way to deal with this requirement is to remove it. Is it possible to code the solution so that each thread owns a device? Or is it possible to rethink the thread's responsibilities so that they communicate by message passing instead of updating shared data? Usually these alternative approaches result in much cleaner and less buggy code. But not always.
You will need locks to protect shared data. The easiest way to do this is with the lock statement, e.g.:
object _mutex = new object();
List<Object> MyDevices = null;
...
var device = ...;
lock (_mutex)
{
MyDevices.Add(device);
}
Generally, you want to minimize the code in the lock statement. Also, you may want to have one lock for the List<Object> and a separate lock for each item in the list, depending on how your thread use those devices.
One thing you might want to consider using is an ObservableCollection. This class implements the INotifyPropertyChanged interface, which notifies any listeners of changes to the underlying collection.
Next, you'll want to implement an event handler for PropertyChanged in your Thread classes like so (I recommend making either an interface or base class that handles this since you appear to be using different classes for each Thread):
public sealed class MyThreadBase
{
private ObservableCollection<object> MyDevices;
public MyThreadBase(ObservableCollection<object> deviceList)
{
MyDevices = deviceList;
MyDevices.PropertyChanged += MyDevices_PropertyChanged; // Register listener
}
private void MyDevices_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
lock (MyDevices)
{
// Do something with the data...
}
}
}
The lock statement is used so that the thread is blocked when another thread is reading or writing to MyDevices. This is typically important in synchronization and is known as the readers-writers problem. I'd suggest reading up on that and possible solutions as well.
If you intend, however, for each thread to iterate over the devices and do something with each one, then you will run into issues, as iterating over a changing collection is not a good idea (and when using a foreach loop, will actually throw an exception), so keep that in mind too.
other threads need to know about the change right away
If you want low latency notifications, threads must spend the majority of time sleeping on something. E.g. executing Dispatcher.Run() that will sleep waiting for messages/tasks to process.
If that’s your case, you can use ObservableCollection instead of List, and write CollectionChanged handler that forwards notifications for your 3 threads. Or if that’s what you want, forward notifications to 2 other threads, excluding the current one, if you won’t want the thread that initiated the change to process changed event.
I'm not sure if the Dispatcher class is available on Windows IoT platform. Definitely not the case for .NET core. Even if not, high-level building blocks to create one are available. Here’s an example implementation that also implements synchronization context, very simple because relies on high-level ConcurrentQueue and BlockingCollection generic classes.
using kvp = KeyValuePair<SendOrPostCallback, object>;
enum eShutdownReason : byte
{
Completed,
Failed,
Unexpected,
}
class Dispatcher : IDisposable
{
const int maxQueueLength = 100;
readonly ConcurrentQueue<kvp> m_queue;
readonly BlockingCollection<kvp> m_block;
public Dispatcher()
{
m_queue = new ConcurrentQueue<kvp>();
m_block = new BlockingCollection<kvp>( m_queue, maxQueueLength );
createdThreadId = Thread.CurrentThread.ManagedThreadId;
prevContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext( new SyncContext( this ) );
}
readonly SynchronizationContext prevContext;
readonly int createdThreadId;
class SyncContext : SynchronizationContext
{
readonly Dispatcher dispatcher;
public SyncContext( Dispatcher dispatcher )
{
this.dispatcher = dispatcher;
}
// https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
public override void Post( SendOrPostCallback cb, object state )
{
dispatcher.Post( cb, state );
}
}
/// <summary>Run the dispatcher. Must be called on the same thread that constructed the object.</summary>
public eShutdownReason Run()
{
Debug.Assert( Thread.CurrentThread.ManagedThreadId == createdThreadId );
while( true )
{
kvp h;
try
{
h = m_block.Take();
}
catch( Exception ex )
{
ex.logError( "Dispatcher crashed" );
return eShutdownReason.Unexpected;
}
if( null == h.Key )
return (eShutdownReason)h.Value;
try
{
h.Key( h.Value );
}
catch( Exception ex )
{
ex.logError( "Exception in Dispatcher.Run" );
}
}
}
/// <summary>Signal dispatcher to shut down. Can be called from any thread.</summary>
public void Stop( eShutdownReason why )
{
Logger.Info( "Shutting down, because {0}", why );
Post( null, why );
}
/// <summary>Post a callback to the queue. Can be called from any thread.</summary>
public void Post( SendOrPostCallback cb, object state = null )
{
if( !m_block.TryAdd( new kvp( cb, state ) ) )
throw new ApplicationException( "Unable to post a callback to the dispatcher: the dispatcher queue is full" );
}
void IDisposable.Dispose()
{
Debug.Assert( Thread.CurrentThread.ManagedThreadId == createdThreadId );
SynchronizationContext.SetSynchronizationContext( prevContext );
}
}
Regardless on whether you’ll use built-in Dispatcher or my custom one, all threads must call it’s Run method, then use asynchronous posted tasks, or async methods, to run code within the dispatcher.

Need strategy for multithreading in unity

My unity project is a procedural environment on Android and creates terrains and stuff at runtime. The overall workflow I use is to calculate anything non-unity in a worker thread and when the data is calculated, I call Unity API within the main thread.
The problem is that sometimes (like every 200 frames) the worker thread affects the main thread's performance. That could show itself with a nasty spike in rendering time.
So what to do with multithreading in unity?
EDIT: The android device is quad core.
EDIT 2: I believe what Sam said in the comments is exactly what's happening.
I wonder if you can determine what core the code is running on, or if
you can set the thread affinity? I found some links where people
described similar situations: here and here. Sounds like
it's picking the same core as the main thread occasionally.
So maybe this is not about unity but every real time interactive multithreaded application. I believe it is possible to set thread affinity on some versions of some platforms but that destroys the cross platform status of the system.
PS: Not exactly the main issue but to make the question more concrete, I will include the worker thread implementation. It is a modified version of the worker thread implementation suggested in this post. The modified version is like this:
public static class JobScheduler
{
private static Queue<Job> Jobs = new Queue<Job>();
private static volatile bool isBusy;
private static ManualResetEvent _workAvailable = new ManualResetEvent(false);
static JobScheduler()
{
var backgroundWorkThread = new Thread(BackgroundThread)
{
IsBackground = true,
Priority = ThreadPriority.Lowest,
Name = "BasicBackgroundWorker Thread"
};
backgroundWorkThread.Start();
}
private static void BackgroundThread()
{
int jobCnt;
while (true)
{
Job? workItem=null;
lock (Jobs)
{
jobCnt = Jobs.Count;
if (jobCnt != 0 && !isBusy)
{
workItem = Jobs.Dequeue();
}
}
if (workItem!=null)
{
isBusy = true;
workItem.Value.callback(workItem.Value.param);
}
else
{
_workAvailable.WaitOne();
_workAvailable.Reset();
}
}
}
public static void AddJob(Job Job)
{
lock (Jobs)
{
Jobs.Enqueue(Job);
}
_workAvailable.Set();
}
public static void JobDone()
{
isBusy = false;
_workAvailable.Set();
}
}
And the Job struct:
public struct Job
{
public object param;
public WaitCallback callback;
public Job(WaitCallback callBackP
, object parameter)
{
callback = callBackP;
param = parameter;
}
}
Whenever needed I call JobScheduler.AddJob to enqueue a job and call JobScheduler.JobDone after the job is done to allow the next job to run.
Also the ThreadPool is not an option since it produces unnecessary garbage and is not very flexible to use.

Threadpool with endless worker threads

I have class which implements an endless worker thread like this example, in my case representing a body. During runtime I will have between 0 and ~8 instances live at any time with instances constantly being created and destroyed.
Most of the time this class has a lifecycle of 30 seconds to 5 minutes but occasionally there may be a number of instances created and destroyed in a relatively short period of time. This is where I tend to run into performance issues given the low spec hardware this code is running on.
I would now like to rewrite the behavior so that I use a ThreadPool for my collection of running workers and I am struggling to find the correct way to structure the code.
Basically the code I have at the moment is something like
public class BodyCollection : IReadOnlyDictionary<ulong, TrackedBody>
{
public void Update()
{
if (createNew)
{
var body = new TrackedBody();
body.BeginTracking();
this.Add(1234, body);
}
if (remove)
{
TrackedBody body = this[1234];
body.StopTracking();
this.Remove(body);
}
}
}
public class TrackedBody
{
private readonly Thread _BiometricsThread;
private volatile bool _Continue = true;
public TrackedBody()
{
_BiometricsThread = new Thread(RunBiometricsThread);
}
public void BeginTracking()
{
_BiometricsThread.Start();
}
public void StopTracking()
{
_Continue = false;
}
private void RunBiometricsThread()
{
while(_Continue)
{
System.Threading.Thread.Sleep(1000);
}
}
}
So how do I re-write the above to utilize a ThreadPool correctly and so that I can cancel running threads on the ThreadPool as required? Do I use CancellationTokens or ManualResetEvents to control the threads?
I strongly believe you should be using more modern methods of asynchronous programming. We are going to use the Task Parallel Library here because it gives you the features you want for free:
Tracking completion
Cancellation
Thread pool
public class TrackedBody
{
public Task BeginTrackingAsync(CancellationToken cancellation)
{
return Task.Run(() => RunBiometricsThread(cancellation));
}
private void RunBiometricsThread(CancellationToken cancellation)
{
while(!cancellation.IsCancellationRequested)
{
Task.Delay(1000, cancellation);
}
}
}
Note that I have removed the async keyword. This was doing nothing on its own.
You can use the task to track the state of the ongoing work. You can use the cancellation token to stop all work.

Can I call Monitor.Pulse from a different class in C#

In an application that I am developing I will be using 2 threads to do various operations. (I will not go into detail here.) These threads work in loops, checking if there is work to be done, doing work, calculating the time they need to wait and waiting. (See below)
public Global : System.Web.HttpApplication
{
private static Thread StartingDateThread;
private static Thread DeadlineDateThread;
private static object o1;
private static object o2;
public static Thread GetStartingDateThreadInstance
{
get
{
if(StartingDateThread==null)
{
StartingDateThread=new Thread(new ThreadStart(MonitorStartingDates));
}
return StartingDateThread;
}
}
public static Thread GetDeadlineThreadInstance
{
get
{
if(DeadlineDateThread==null)
{
DeadlineDateThread=new Thread(new ThreadStart(MonitorDeadlines));
}
return DeadlineDateThread;
}
}
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
public static object GetSecondObjectInstance
{
get
{
if(o2==null)
{
o2=new object();
}
return o2;
}
}
protected void Application_Start(object sender, EventArgs e)
{
GetStartingDateThreadInstance.Start();
GetDeadlineThreadInstance.Start();
//////////////////////
////Do other stuff.
}
public void MonitorStartingDates()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetFirstObjectInstance);
}
else
{
Monitor.Enter(GetFirstObjectInstance);
Monitor.Wait(new TimeSpan(12, 0, 0));
Monitor.Exit(GetFirstObjectInstance);
}
}
}
public void MonitorDeadlines()
{
while(true)
{
//Check if there is stuff to do.
//Do stuff if available.
//Check if there will be stuff to do in the future and if there is, check
//the time to wake up.
//If there is nothing to do, sleep for a pre-determined 3 days and 12 hours.
if(StuffToDoInFuture)
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(WaitingTime);
Monitor.Exit(GetSecondObjectInstance);
}
else
{
Monitor.Enter(GetSecondObjectInstance);
Monitor.Wait(new TimeSpan(3, 12, 0, 0));
Monitor.Exit(GetSecondObjectInstance);
}
}
}
As you can see these two threads are started in the Application_Start method in the asax file. They operate if there is stuff available to do and then they calculate the time period they need to wait and then they wait. However, as users of the web application do operations new records will be inserted into the database and there will be circumstances where any of the two threads will have to resume operation sooner than planned. So, say I have a method in my DataAccess class which inserts into the database new data. (See below)
public class DataAccess
{
///////////////
//
public void InsertNewAuction()
{
///Insert new row calculate the time
Monitor.Pulse(Global.GetFirstObjectInstance);
Monitor.Pulse(Global.GetSecondObjectInstance);
///
}
}
It seems like this is an invalid operation, because at the stage where the Monitor.Pulse is called from the InsertNewAuction method I get an exception. Something like "Object synchronization method was called from an unsynchronized block of code." Is there any way of doing this? Thanks for your help
As to the specific error you're seeing, this is because Monitor.Pulse must be called inside the Monitor lock, like this (I've used lock rather than Enter/Exit, as it's safer for making sure the lock is always released, since it uses a proper try/finally block):
lock (Global.GetFirstObjectInstance)
{
Monitor.Pulse(Global.GetFirstObjectInstance);
}
In regard to the more general design question here, it's often dangerous to expose lock objects as public (or even worse, global) fields. In particular, it can be a recipe for deadlocks when multiple global locks are exposed and acquired in differing orders or when you have cases like blocking dispatches to the UI thread while holding a lock. Consider looking into alternate ways to accomplish what you're after.
As noted in the other answer, you have to acquire the lock before you can call Monitor.Pulse() on the monitor object.
That said, your code has at least one other serious bug: you are not initializing the synchronization object in a thread-safe way, which could easily lead to two different threads using two different object instances, resulting in no synchronization between those threads:
public static object GetFirstObjectInstance
{
get
{
if(o1==null)
{
o1=new object();
}
return o1;
}
}
If two threads call this getter simultaneously, they each may see o1 as null and try to initialize it. Then each might return a different value for the object instance.
You should simply initialize the object in a initializer:
private static readonly object o1 = new object();
And then return it from the getter:
public static object GetFirstObjectInstance { get { return o1; } }
That addresses the thread-safety issue. But you still have other issues with the code. First, you should encapsulate synchronization in an object, not expose the actual synchronization object instance. Second, assuming you are going to expose the synchronization object, I don't understand why you bother with the property, since you made the field public. The field should be private if you want to use a property as well.
It would also be better if the property followed normal .NET naming conventions. A method that returned the object would have "Get" in the name, but a property would not. Just name it "FirstObjectInstance".
Also as noted by Dan, use lock everywhere you want to acquire the lock.
There may be other issues in the code as well...I didn't do a thorough review. But the above you need to fix for sure.

Non-blocking concurrent collection?

System.Collections.Concurrent has some new collections that work very well in multithreaded environments. However, they are a bit limited. Either they block until an item becomes available, or they return default(T) (TryXXX methods).
I'm needing a collection that is thread safe, but instead of blocking the calling thread it uses a callback to inform me that at least one item is available.
My current solution is to use a BlockingCollection, but to use the APM with a delegate to get the next element. In other words, I create a delegate to a method that Takes from the collection, and execute that delegate using BeginInvoke.
Unfortunately, I have to keep a lot of state within my class in order to accomplish this. Worse, the class is not thread safe; it can only be used by a single thread. I'm skirting the edge of maintainability, which I'd prefer not to do.
I know there are some libraries out there that make what I'm doing here pretty simple (I believe the Reactive Framework is one of these), but I'd like to accomplish my goals without adding any references outside of version 4 of the framework.
Are there any better patterns I can use that don't require outside references that accomplish my goal?
tl;dr:
Are there any patterns that satisfy the requirement:
"I need to signal a collection that I am ready for the next element, and have the collection execute a callback when that next element has arrived, without any threads being blocked."
I think I have two possible solutions. I am not particularly satisfied with either, but they do at least provide a reasonable alternative to the APM approach.
The first does not meet your requirement of no blocking thread, but I think it is rather elegant because you can register callbacks and they will get called in round-robin fashion, but you still have the ability to call Take or TryTake as you normally would for a BlockingCollection. This code forces callbacks to be registered each time an item is requested. That is the signalling mechanism for the collection. The nice thing about this approach is that calls to Take do not get starved as they do in my second solution.
public class NotifyingBlockingCollection<T> : BlockingCollection<T>
{
private Thread m_Notifier;
private BlockingCollection<Action<T>> m_Callbacks = new BlockingCollection<Action<T>>();
public NotifyingBlockingCollection()
{
m_Notifier = new Thread(Notify);
m_Notifier.IsBackground = true;
m_Notifier.Start();
}
private void Notify()
{
while (true)
{
Action<T> callback = m_Callbacks.Take();
T item = Take();
callback.BeginInvoke(item, null, null); // Transfer to the thread pool.
}
}
public void RegisterForTake(Action<T> callback)
{
m_Callbacks.Add(callback);
}
}
The second does meet your requirement of no blocking thread. Notice how it transfers the invocation of the callback to the thread pool. I did this because I am thinking that if it got executed synchronously then the locks would be held longer resulting in the bottlenecking of Add and RegisterForTake. I have looked it over closely and I do not think it can get live locked (both an item and a callback are available, but the callback never gets executed) but you might want to look it over yourself to verify. The only problem here is that a call to Take would get starved as callbacks always take priority.
public class NotifyingBlockingCollection<T>
{
private BlockingCollection<T> m_Items = new BlockingCollection<T>();
private Queue<Action<T>> m_Callbacks = new Queue<Action<T>>();
public NotifyingBlockingCollection()
{
}
public void Add(T item)
{
lock (m_Callbacks)
{
if (m_Callbacks.Count > 0)
{
Action<T> callback = m_Callbacks.Dequeue();
callback.BeginInvoke(item, null, null); // Transfer to the thread pool.
}
else
{
m_Items.Add(item);
}
}
}
public T Take()
{
return m_Items.Take();
}
public void RegisterForTake(Action<T> callback)
{
lock (m_Callbacks)
{
T item;
if (m_Items.TryTake(out item))
{
callback.BeginInvoke(item, null, null); // Transfer to the thread pool.
}
else
{
m_Callbacks.Enqueue(callback);
}
}
}
}
How about something like this? (The naming could probably use some work. And note that this is untested.)
public class CallbackCollection<T>
{
// Sychronization object to prevent race conditions.
private object _SyncObject = new object();
// A queue for callbacks that are waiting for items.
private ConcurrentQueue<Action<T>> _Callbacks = new ConcurrentQueue<Action<T>>();
// A queue for items that are waiting for callbacks.
private ConcurrentQueue<T> _Items = new ConcurrentQueue<T>();
public void Add(T item)
{
Action<T> callback;
lock (_SyncObject)
{
// Try to get a callback. If no callback is available,
// then enqueue the item to wait for the next callback
// and return.
if (!_Callbacks.TryDequeue(out callback))
{
_Items.Enqueue(item);
return;
}
}
ExecuteCallback(callback, item);
}
public void TakeAndCallback(Action<T> callback)
{
T item;
lock(_SyncObject)
{
// Try to get an item. If no item is available, then
// enqueue the callback to wait for the next item
// and return.
if (!_Items.TryDequeue(out item))
{
_Callbacks.Enqueue(callback);
return;
}
}
ExecuteCallback(callback, item);
}
private void ExecuteCallback(Action<T> callback, T item)
{
// Use a new Task to execute the callback so that we don't
// execute it on the current thread.
Task.Factory.StartNew(() => callback.Invoke(item));
}
}

Categories