I have the class ComputationService which is the wrapper of the old legacy COM object. This COM object cannot have multiple instances because of how its implemented.
In the application, there are two buttons (for simplification) when clicked a new Task runs which use a ComputationService these tasks are kind of long-running tasks so you can click on the second button when the first one is in the process of computing. That's where the problem occurs because I can't let both threads use the ComputationService so I decided to use Mutex to allow only one instance of ComputationService at the time.
What I have:
public class ComputationService : IComputationService
{
public ComputationService()
{
_mutex = new Mutex(true, "AwesomeMutex");
_mutex.WaitOne();
}
public void Dispose()
{
_mutex.ReleaseMutex();
}
}
and then two places where I use it:
public Task Compute1()
{
return Task.Run(() =>
{
foreach (var item in items)
{
using (var service = _computationFactory()) // new instance of ComputationService
{
//Do some work
}
}
});
}
public Task Compute2()
{
return Task.Run(() =>
{
foreach (var item in items)
{
using (var service = _computationFactory()) // new instance of ComputationService
{
//Do some other work
}
}
});
}
What I get when I am debugging to console:
Mutex created by Thread: 18
Wait, thread: 18
Do Work, thread: 18
Mutex created by Thread: 20
Wait, thread: 20
Mutex release by thread: 18
Mutex created by Thread: 18
Wait, thread: 18
Do Work, thread: 18
Mutex release by thread: 18
Then of course AbandonedMutexException() occurs on Thread 20.
I tried to use lock in the constructor of ComputationService but did not work.
Can you please help me, what I am doing wrong and how to fix it?
Problem is here:
_mutex = new Mutex(true, "AwesomeMutex");
_mutex.WaitOne();
You are passing true as first argument, named initiallyOwned. If you pass true there - that means IF mutex with such name did not exist before and is created as a result of this constructor - current thread now owns it. You don't check if mutex was created as a result of this call, and actually there is even no way to check that when using this constructor overload. So never ever pass true if using this constructor.
If you want to utilize initiallyOwned - then use another overload, which actually tells you whether mutex was created as a result of this constructor:
_mutex = new Mutex(true, "AwesomeMutex", out var createdNew);
Now, if createdNew returned true - you do NOT need to call _mutex.WaitOne(), because as per above - current thread already owns the mutex. That's what happens in your case - sometimes you already own the mutex and then you call _mutex.WaitOne(). Now to release it you would have to call Release() twice, which you never do.
Alternatively, just pass false, then wait:
_mutex = new Mutex(false, "AwesomeMutex");
_mutex.WaitOne();
If the whole thing happens in the same process, then you don't need global mutex (which you now have because you pass a name) - you can do fine with a local one:
public class ComputationService : IDisposable {
// one static instance
private static readonly Mutex _mutex = new Mutex();
public ComputationService()
{
_mutex.WaitOne();
}
public void Dispose() {
_mutex.ReleaseMutex();
}
}
There are other improvements that can be made, but they are out of scope of this question.
As mentioned in comments - in single process lock (Monitor.Enter \ Monitor.Exit) will be faster and achieve the same result in your case:
public class ComputationService : IDisposable {
// one static instance
private static readonly object _mutex = new object();
public ComputationService()
{
Monitor.Enter(_mutex);
}
public void Dispose() {
Monitor.Exit(_mutex);
}
}
Related
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.
Consider the following pseudo code.
static class Tools
{
static readonly UnmanagedType ut = new UnmanagedType ();
}
What is the best pattern for this scenario such that the unmanaged static instance can be guaranteed to get released to the system right after the application exits?
My rough idea is to compulsorily subscribe Tools disposing method to the system's close event right after ut is instantiated in Tools class. Is it possible? How?
Singleton?
sealed class Tools
{
public static readonly Tools Instance = new Tools();
private UnmanagedType ut = new UnmanagedType ();
~Tools() {
// TODO: destroy this.ut
}
}
I have seen several answers to the similar questions (i.e. “How to release/dispose objects/resources in static class once a process exits”). All the answers basically state that
a) static class in C# cannot have destructor (which is correct),
b) and therefore you cannot release resources at the end of static class life,
c) hence you MUST turn your class to non-static to dispose/release objects/resources.
I disagree with the items b) and c) and suggest the following solution for disposing the objects in static class on exit:
In your static class constructor or any first call to its method that creates the object(s) to dispose:
a) save a main process thread reference (Thread.CurrentThread);
b) start a new thread (Watcher) that monitors whether the main thread is running.
Once the main thread dies, the Watcher disposes/releases the objects/resources and exits.
Example code:
using System.Threading;
public static class StaticDisposer
{
private static Thread mParentProcThread = null;
private static Thread mDisposerThread = null;
// Other class members:
………………………………………………
// Objects to be disposed at the process exit:
// Ex.: private/public static … obj1ToDispose = null;
………………………………………………
static StaticDisposer()
{
mParentProcThread = Thread.CurrentThread;
mDisposerThread = new Thread(DisposerThreadBody);
mDisposerThread.Start();
}
// Methods of the class:
………………………………………………
private static void DisposerThreadBody()
{
while (mParentProcThread != null && mParentProcThread.IsAlive)
{
Thread.Sleep(500);
}
// Dispose objects, release resources, close streams, delete temporary files, etc.:
//if(obj1ToDispose != null)
// <Dispose code>
// ………………………………………………………………………………
}
}
NB! If you have several threads in your program that are using your static class with the suggested disposing logic and you want the disposing to happen only when the main thread stops, then the main thread MUST call/set/get any method/property of the static class before the secondary threads do.
Forgive me, I'm learning C# and object-oriented programming. I am running two threads. Thread #2 calls a different class method. This method assigns an object's data value. Thread #1 unsuccessfully attempts to access the object's data value that Thread #2 assigned. The object's data value in Thread #1 is null. How do I access this object and all its assigned data values? I basically want to save the data variables from Thread #2 classes and access them from a Thread #1 class. It appears an object and it's data member values generated in a Thread #2 class are null when I leave the class and then try to access the same object in a Thread #1 class. Can I still save the instantiated object values in my example or should I declare things as static? Below is some of my code to illustrate my problem. Thank you for anyone that can recommend or illustrate how to resolve this.
// this is a main operating class that: 1) starts two threads and 2) trys to access the Thread #2 Lru_SetChanFreq class object data from Thread #1 Lru_operations class
public class Lru_operation
{
[STAThread]
static void Main()
{
// starts a separate thread #2
Lru_Listen LruListen1 = new Lru_Listen();
Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
LruListenThread.Start();
while(!LruListenThread.IsAlive)
;
Thread.Sleep(1);
// follows the main thread #1
Lru_operation LruOpX = new Lru_operation();
LruOpX.LruOperation();
}
// this is where main thread #1 operates
public void LruOperation()
{
// create object to access object data from thread #2 Lru_SetChanFreq class
Lru_SetChanFreq SetChFrq = new Lru_SetChanFreq();
try
{
// do stuff
// ERROR: SetChFrq.LruSetFrq.RxFreq2 = null and then catches an exception to go below.
// Why is this happening if Thread #2 previously sets RxFreq2 = 405.1?
Console.WriteLine("LruSetFrq.RxFreq2 = {0}", SetChFrq.LruSetFrq.RxFreq2);
// do more stuff
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "connection terminated",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// this is called from thread #2. It's object is used by thread #1
public class Lru_SetChanFreq
{
#region fields
private string rxFreq2;
private Lru_SetChanFreq mLruSetFrq;
#endregion fields
#region Properties
public Lru_SetChanFreq LruSetFrq
{
get { return mLruSetFrq; }
set { mLruSetFrq = value; }
}
public string RxFreq2
{
get { return rxFreq2; }
set { rxFreq2 = value; Console.WriteLine("rxFreq2 = {0}", rxFreq2); }
}
#endregion Properties
#region methods
public Lru_SetChanFreq()
{
}
public void SetFreq()
{
mLruSetFrq = new Lru_SetChanFreq();
mLruSetFrq.RxFreq2 = "405.1";
// I confirmed that LruSetFrq.RxFreq2 = 405.1
Console.WriteLine("LruSetFrq.RxFreq2 = {0}", LruSetFrq.RxFreq2);
// do stuff
}
#endregion methods
}
// this is starting point of thread #2
public class Lru_Listen
{
#region Fields
// stuff
#endregion Fields
#region Properties
// stuff
#endregion Properties
#region Methods
public void ListenForAag()
{
// do stuff
LruListenAccReq();
}
public void LruListenAccReq()
{
// do stuff
LruShowRequestData(request);
}
public void LruShowRequestData(// stuff )
{
Lru_SetChanFreq SetChanFreq = new Lru_SetChanFreq();
SetChanFreq.SetFreq(); // calls to another class method
}
#endregion Methods
}
}
Your 2 Threads each make an instance of Lru_SetChanFreq . The 2 instances are not related or coupled. Setting a value on one thread (SetChanFreq.SetFreq()) has no bearing on the other thread.
A few points:
Try to pick meaningful, readable names. Prefixes like Lru_ have a negative impact on readability.
Study the meaning of object-instance (vs static) first. Leave threading alone until you have a good grasp of objects and memory management.
In the end you probably won't want to use Threads at all, ThreadPool and Task are more efficient and convenient.
Your issue is that you are initializing and accessing distinct Lru_SetChanFreq instances in your two threads. You should initialize just one, assign it to a class field, and then access the same instance from the other thread. Here is a trimmed-down version of your code that does that:
public class Lru_operation
{
[STAThread]
static void Main()
{
Lru_Listen LruListen1 = new Lru_Listen();
// Run LruListen1 on Thread 2
Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
LruListenThread.Start();
// Wait for its operation to complete
// There is no need to wait for the thread to terminate
LruListen1.readyEvent.WaitOne();
// Read the Lru_SetChanFreq initialized from LruListen1,
// and continue processing it on Thread 1
Lru_operation LruOpX = new Lru_operation();
LruOpX.LruOperation(LruListen1.SetChanFreq);
}
public void LruOperation(Lru_SetChanFreq setChanFreq)
{
// Access the original Lru_SetChanFreq instance received as parameter
}
}
// this is starting point of thread #2
public class Lru_Listen
{
// Declare Lru_SetChanFreq as a field so as to access it externally
internal Lru_SetChanFreq SetChanFreq;
// Our thread synchronization event
internal ManualResetEvent readyEvent = new ManualResetEvent(false);
public void LruShowRequestData(// stuff )
{
this.SetChanFreq = new Lru_SetChanFreq();
SetChanFreq.SetFreq(); // calls to another class method
// Signal that we are ready
readyEvent.Set();
}
}
Update: I've edited my code to introduce proper thread synchronization (to replace the OP's while (LruListenThread.IsAlive) and Thread.Sleep(1)). This consists of three parts:
Creating a ManualResetEvent instance that can be accessed by both threads.
Calling WaitOne from Thread 1, in order to make it wait.
Calling Set from Thread 2 once it completes initializing your Lru_SetChanFreq, thereby signalling to Thread 1 that it may proceed.
This question already has answers here:
how to obtain a lock in two places but release on one place?
(4 answers)
Closed 8 years ago.
I want to reask my previous question how to obtain a lock in two places but release on one place? because it seems too old and noone sees my updated code.
The question is - is my code correct and how to fix it if not?
I've tried similar code in the application and it hangs, but I don't now why, so I guess probably my code still wrong...
public void obtainLock() {
if (needCallMonitorExit == false) {
Monitor.Enter(lockObj);
needCallMonitorExit = true;
}
// doStuff
}
public void obtainReleaseLock() {
try {
lock (lockObj) {
// doAnotherStuff
}
} finally {
if (needCallMonitorExit == true) {
needCallMonitorExit = false;
Monitor.Exit(lockObj);
}
}
}
One of my methods should obtain the lock. another method should obtain the same lock and release it. sometimes just obtainReleaseLock is called. sometimes obtainLock is called (probably several times) and after a while obtainReleaseLock is called. These two methods are always called from the same thread, however lockObj is used in another thread for synchronization.
If you really need to go this way and don't want to use the alternatives provided by Marc, at least, put it into its own class:
public class LockObject
{
object _syncRoot = new object();
object _internalSyncRoot = new object();
public LockToken Lock()
{
lock(_internalSyncRoot)
{
if(!_hasLock)
{
Monitor.Enter(_syncRoot);
_hasLock = true;
}
return new LockToken(this);
}
}
public void Release()
{
lock(_internalSyncRoot)
{
if(!_hasLock)
return;
Monitor.Exit(_syncRoot);
_hasLock = false;
}
}
}
public class LockToken : IDisposable
{
LockObject _lockObject;
public LockToken(LockObject lockObject) { _lockObject = lockObject; }
public void Dispose() { _lockObject.Release(); }
}
This would allow you to use it like this:
LockObject _lockObj = new LockObject();
public void obtainLock()
{
_lockObj.Lock();
// doStuff
}
public void obtainReleaseLock()
{
using(_lockObj.Lock())
{
// doAnotherStuff
}
}
One word of caution:
If your thread is aborted after the call to obtainLock and before the call to obtainReleaseLock, your program will deadlock.
If you use Monitor.Enter you will need to call exactly that many Monitor.Exit calls on the same object, on the same thread. By using a lock block this is automatically done for you - as soon as you are outside the scope of the lock block, the lock count is decreased. Within the same thread it is perfectly legal to lock multiple times on the same object (via both mechanisms).
Keeping that in mind, maintaining your own "lock state" variable would only make things more complex. What if two threads access the needCallMonitorExit variable at the same time?
If I were you I would stick to lock blocks, and re-order code to fit inside them. Put as little code inside the blocks as possible.
I am using a System.Threading.ThreadPool to manage a queue of jobs from a service. I have already implemented logging like this...
abstract class Global
{
public static LogFile LogFile = null;
}
public class LogFile : IDisposable
{
private StreamWriter sw;
public LogFile(string path){}
public void WriteEntry(string logText)
{
lock (sw)
{
sw.WriteLine(logText);
}
}
}
I want to create the log at service startup and use it from my queued worker threads.. something like this...
//On Service Start
Global.LogFile = new LogFile("log.txt");
//Kick of worker thread
ThreadPool.QueueUserWorkItem(objWrkrThread.CallbackMethod, iCount);
//Worker thread logs an entry in CallbackMethod()
Global.LogFile.WriteEntry("Hello World");
Is this safe? Will calling a method on a static instance of a class inadvertently 'synchronise' or 'block' my threads?
Michael
Nothing will 'synchronize' or 'block' unless you write code in your method. It doesn't matter whether it's an instance method or static method.
So by default, WriteEntry won't block any calls from your threads but it could very well corrupt file if you don't write the code to handle multiple simultaneous calls.
Read more on this topic here:
Are static methods thread safe
It's not safe to have multiple threads call WriteEntry at the same time unless it was designed to be safe.
What you are trying to do sounds like the perfect candidate for a Singleton class. I know it gets a bad wrap, but sometimes it's simplicity is worth it.
You can create a log class like this and you should be thread safe.
public sealed class Log
{
static Log instance=null;
static readonly object lockObject = new object();
static string path = "log.txt";
Log()
{
}
public static Log Instance
{
get
{
lock (lockObject)
{
if (instance==null)
{
instance = new Log();
}
return instance;
}
}
}
public void WriteLine(string message)
{
lock(lockObject)
{
using(StreamWriter sw = new StreamWriter(File.Open(path, FileMode.Append)))
{
sw.WriteLine(message);
}
}
}
}
Then in your code, you just call it like this:
Log executionLog = Log.Instance;
executionLog.WriteLine("this is a log message.");
You could also manage opening the file in similar thread safe methods to get rid of the over head of opening and closing the file every write.