I have a LongOperationHelper that I activate on each potentially long operation.
It displays a semi transparent layer and does not allow any click until the operation ends and a spinning control to indicate progress.
It looks something like that (missing some business logic but the idea is clear I think):
Edited: (Added the missing code of the common states that actually needed the locking - this is more like the problematic code)
(My solution is posted in an answer bellow)
public static class LongOperationHelper
{
private static object _synchObject = new object();
private static Dictionary<string, int> _calls = new Dictionary<string, int>();
private static Action<string> DisplayLongOperationRequested;
private static Action<string> StopLongOperationRequested;
public static void Begin(string messageKey)
{
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
_calls[messageKey]++;
}
else
{
_calls.Add(messageKey, 1);
DispatcherHelper.InvokeIfNecesary(() =>
{
//Raise event for the MainViewModel to display the long operation layer
DisplayLongOperationRequested?.Invoke(messageKey);
});
}
}
}
public static void End(string messageKey)
{
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
if (_calls[messageKey] > 1)
{
_calls[messageKey]--;
}
else
{
_calls.Remove(messageKey);
DispatcherHelper.InvokeIfNecesary(() =>
{
//Raise event for the MainViewModel to stop displaying the long operation layer
StopLongOperationRequested?.Invoke(messageKey);
});
}
}
else
{
throw new Exception("Cannot End long operation that has not began");
}
}
}
}
So as you can probably see, there is a potential deadlock in there, if:
Someone calls Begin from a non UI thread.
It enters the lock
Someone calls Begin or End from a UI thread and gets locked
The first Begin call tries to Dispatch to the UI thread.
Result: Deadlock!
I want to make this Helper thread safe, so that any thread might call Begin, or End at any given time, interested to see if there is any known pattern, any Ideas?
Thanks!
Don't lock for the entire method. Lock only when you touch the fields that need it, and unlock as soon as you're done. Lock and unlock each time you touch those fields. Otherwise, you'll end up with deadlocks like this.
You can also consider using ReaderWriterLockSlim, which differentiates between read locks and write locks. It lets multiple threads read at the same time, but locks everyone out when a write lock is taken. There is an example on how to use it in that documentation.
The entire purpose of having a "UI thread" is to avoid synchronization exactly like this. The fact that all UI code needs to run on a single thread means that it, by definition, cannot run concurrently. You have no need to use locks to make your UI code run atomically because it's all running on a single thread.
Writing UI code that required the programmer to do their own locking is sufficiently hard and error prone that the whole framework was designed around the idea that it's unreasonable to expect people to do it (correctly), and that it's much easier to simply force all UI code to go into a single thread, where other synchronization mechanisms won't be needed.
Here is the "Deadlock free" code:
I have relocated the dispatching to the UI thread to outside of the lock.
(Can someone still see a potential deadlock here?)
public static class LongOperationHelper
{
private static object _synchObject = new object();
private static Dictionary<string, int> _calls = new Dictionary<string, int>();
private static Action<string> DisplayLongOperationRequested;
private static Action<string> StopLongOperationRequested;
public static void Begin(string messageKey)
{
bool isRaiseEvent = false;
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
_calls[messageKey]++;
}
else
{
_calls.Add(messageKey, 1);
isRaiseEvent = true;
}
}
//This code got out of the lock, therefore cannot create a deadlock
if (isRaiseEvent)
{
DispatcherHelper.InvokeIfNecesary(() =>
{
//Raise event for the MainViewModel to display the long operation layer
DisplayLongOperationRequested?.Invoke(messageKey);
});
}
}
public static void End(string messageKey)
{
bool isRaiseEvent = false;
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
if (_calls[messageKey] > 1)
{
_calls[messageKey]--;
}
else
{
_calls.Remove(messageKey);
isRaiseEvent = true;
}
}
else
{
throw new Exception("Cannot End long operation that has not began");
}
}
//This code got out of the lock, therefore cannot create a deadlock
if (isRaiseEvent)
{
DispatcherHelper.InvokeIfNecesary(() =>
{
StopLongOperationRequested?.Invoke(messageKey);
});
}
}
}
Related
I have searched a lot and it seems C# async await has to be used together with Task.
The situation is that I have a method that is very time consuming which is OK, but I hope it won't block the main method.
So I describe the main method as "async", and inside it, I call and "await" the time consuming method, but C# need the time consuming method to be included in a Task which means it will be executed in a seperate thread. But that method has something that cannot run outside main thread.
And my question is how can I run the time consuming method asynchronously without putting it in a different thread?
Thank you very much.
PS: I'm doing this in Unity3D, is it possible to leverage Coroutine to reach the goal?
//main method
private async void MainMethod()
{
//...
bool result = await TimeConsumingMethod();
//...
}
//time consuming method
private async Task<bool> TimeConsumingMethod()
{
bool result;
await Task.Run(()=>
{
//...
//SOME CODE THAT CANNOT run in thread other than main
//...
});
return result;
}
To run anything aysnchronously (not blocking the main thread) in unity you have to use a different Thread/Task.
But as you also want to run code on the main thread in that separate thread you'll have to communicate between the two.
Although you can't run anything on the main thread from inside a different thread. You can make a queue that the main thread consistently handles. When the off thread then wants to do something on the main thread it adds it to the queue and the mainThreadHandler will then handle it in the next frame update. So the off thread can then tell the main thread that it wants to do something on the main thread and wait for the main thread to be done with that code and then continue with the processing after.
This is an implementation of a main thread handler:
public class MainThreadHandler:MonoBehaviour
{
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
public void Update()
{
lock (_executionQueue)
{
while (_executionQueue.Count > 0)
{
_executionQueue.Dequeue().Invoke();
}
}
}
public static void Enqueue(Action action)
{
lock (_executionQueue)
{
_executionQueue.Enqueue(action);
}
}
}
Calling your code including calling things in the main thread and then waiting for it will then look something like this:
private Task currentTask;
private bool taskResult;
public void StartOffThreadMethod()
{
currentTask = Task.Run(() =>
{
DoCalculationsOffThread();
bool isMainThreadDone = false;
MainThreadHandler.Enqueue(() =>
{
//Main thread code
//Either set a bool that the off thread checks to see if the action has been completed
//or start a new task that handles the rest of the off threaded code
//This example uses a isDone bool
isMainThreadDone = true;
});
while (!isMainThreadDone)
{
Thread.Sleep(100);
}
DoOtherCalculationsOffThread();
taskResult = true;
});
}
private void Update()
{
if (currentTask != null && currentTask.IsCompleted)
{
//do stuff with the result
}
}
I'd also like to add that going back and forth between the main thread and an calculating thread can be rather tricky business. If it can be prevented i would try to prevent it.
I am implementing a logger which writes records to the database. In order to prevent the database writes from blocking the code which is calling the logger, I've moved the DB access to a separate thread, implemented using a producer/consumer model based on BlockingCollection<string>.
Here's the simplified implementation:
abstract class DbLogger : TraceListener
{
private readonly BlockingCollection<string> _buffer;
private readonly Task _writerTask;
DbLogger()
{
this._buffer = new BlockingCollection<string>(new ConcurrentQueue<string>(), 1000);
this._writerTask = Task.Factory.StartNew(this.ProcessBuffer, TaskCreationOptions.LongRunning);
}
// Enqueue the msg.
public void LogMessage(string msg) { this._buffer.Add(msg); }
private void ProcessBuffer()
{
foreach (string msg in this._buffer.GetConsumingEnumerable())
{
this.WriteToDb(msg);
}
}
protected abstract void WriteToDb(string msg);
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Signal to the blocking collection that the enumerator is done.
this._buffer.CompleteAdding();
// Wait for any in-progress writes to finish.
this._writerTask.Wait(timeout);
this._buffer.Dispose();
}
base.Dispose(disposing);
}
}
Now, when my application shuts down, I need to make sure that the buffer is flushed before the database connection goes down. Otherwise, WriteToDb will throw an exception.
So, here's my naive Flush implementation:
public void Flush()
{
// Sleep until the buffer is empty.
while(this._buffer.Count > 0)
{
Thread.Sleep(50);
}
}
The problem with this implementation is the following sequence of events:
There is one entry in the buffer.
In the logging thread, MoveNext() is called on the enumerator, so we're now in the body of ProcessBuffer's foreach loop.
Flush() is called by the main thread. It sees that the collection is empty, so returns immediately.
The main thread closes the DB connection.
Back in the logging thread, the body of the foreach loop starts executing. WriteToDb is called, and fails because the DB connection has been closed.
So, my next try was adding some flags, like so:
private volatile bool _isWritingBuffer = false;
private void ProcessBuffer()
{
foreach (string msg in this._buffer.GetConsumingEnumerable())
{
lock (something) this._isWritingBuffer = true;
this.WriteToDb(msg);
lock (something) this._isWritingBuffer = false;
}
}
public void Flush()
{
// Sleep until the buffer is empty.
bool isWritingBuffer;
lock(something) isWritingBuffer = this._isWritingBuffer;
while(this._buffer.Count > 0 || isWritingBuffer)
{
Thread.Sleep(50);
}
}
However, there's still a race condition, since the entire Flush() method could execute after the collection is empty but before _isWritingBuffer gets set to true.
How can I fix my Flush implementation to avoid this race condition?
Note: For various reasons, I must write the logger from scratch, so please don't answer with a suggestion that I use some existing logging framework.
First never ever lock on a public object, especially this.
Moreover never ever use bare booleans for synchronization: see my blog if you want to have a glimpse in what can go wrong: Synchronization, memory visibility and leaky abstractions :)
Concerning the issue itself I must be missing something but why do you need such a Flush method?
Indeed when you're done with your logging you will dispose of the logger by calling its Dispose method from the main thread.
And you have implemented it in such a way that it will wait for the "write to DB" task.
If I'm wrong and you really need to synchronize with another primitive then you should use an event:
In the DbLogger:
public ManualResetEvent finalizing { get; set; }
public void Flush()
{
finalizing.WaitOne();
}
And somewhere, e.g. in ProcessBuffer you notify when you're done with writing to DB:
finalizing.Set();
I've written a WPF WizardFramework which performs some actions in the background using some BackgroundWorker. While processing it can happen that I have to update an ObservableCollection which is bound to my UI.
For this case I've written a ThreadableObservableCollection, which provides threadsafe methods for Insert, Remove and RemoveAt. Though I'm using .NET 4.5 I was not able to get BindingOperations.EnableCollectionSynchronization working without many other invalid access exceptions. My Collection looks like:
public class ThreadableObservableCollection<T> : ObservableCollection<T>
{
private readonly Dispatcher _dispatcher;
public ThreadableObservableCollection()
{
_dispatcher = Dispatcher.CurrentDispatcher;
}
public void ThreadsafeInsert(int pos, T item, Action callback)
{
if (_dispatcher.CheckAccess())
{
Insert(pos, item);
callback();
}
else
{
_dispatcher.Invoke(() =>
{
Insert(pos, item);
callback();
});
}
}
[..]
}
This is working as expected, while I am using the wizard in my application. Now I'm using NUnit to write some integrationtests for the application.
There's a listener which waits for the WizardViewModel to finish it's work and looking for some pages which are injected in the Steps-Collection. After the asyncrone work is done I can use Validate to check the viewmodel state.
Unfortunately I'm using a ManualResetEvent to wait for the wizard to close. This looks like following:
public class WizardValidator : IValidator, IDisposable
{
private WizardViewModel _dialog;
private readonly ManualResetEvent _dialogClosed = new ManualResetEvent(false);
[..]
public void ListenTo(WizardViewModel dialog)
{
_dialog = dialog;
dialog.RequestClose += (sender, args) => _dialogClosed.Set();
dialog.StepsDefaultView.CurrentChanged += StepsDefaultViewOnCurrentChanged;
_dialogClosed.WaitOne();
}
[..]
}
Now there's a problem:
While the Application is running the UI Thread is not blocked, the Collection can be updated without any problems. But in my testcases the "main" Thread where I initialize the ViewModel (and because of that the Collections) is an AppDomainThread which is blocked by the testcode. Now my ThreadsafeInsert wants to update the collection but cannot use the AppDomain Thread.
But I have to wait for the wizard to finish, how can I solve this kind of deadlock? Or is there a more elegant solution for this one?
edit:
I worked around this problem with a check if there's a user interface, and only then I invoke on the Application-Thread, otherwise I change the collection intentionally on another thread. This does not prevent the exception, but it is not recognized from the test... the items are inserted nevertheless, only the NotifyCollectionChanged-Handler is not called (which is only used in the UI anyway).
if (Application.Current != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
Steps.Insert(pos, step);
stepsView.MoveCurrentTo(step);
});
}
else
{
new Action(() => Steps.Insert(pos, step)).BeginInvoke(ar => stepsView.MoveCurrentToPosition(pos), null);
}
This is an ugly workaround and I am still interested in a clean solution.
Is there a way to use an alternate Dispatcher to create (e.g.) the whole ViewModel and use this to change my collection?
As I see the main problem that main thread is blocked and other operations are trying to be executed in main thread too? What about not to block main thread, like this:
// helper functions
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
// in your code:
while(!_dialogClosed.WaitOne(200))
DoEvents();
If it will not help then I guess need to try some SynchronisationContext workarounds.
I think the problems boil down to the fact that you create ObservableCollection that is tied to Dispatcher object.
Involving Dispatcher object directly is almost never good idea(as you just witnessed). Instead I would suggest you to see how others have implemented ThreadSafeObservableCollection. This is a little example I put together, it should illustrate the point:
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
private readonly object _lock = new object();
public ThreadSafeObservableCollection()
{
BindingOperations.CollectionRegistering += CollectionRegistering;
}
protected override void InsertItem(int index, T item)
{
lock (_lock)
{
base.InsertItem(index, item);
}
}
private void CollectionRegistering(object sender, CollectionRegisteringEventArgs e)
{
if (e.Collection == this)
BindingOperations.EnableCollectionSynchronization(this, _lock);
}
}
I have to make a Instant Messenger server in C#. The server is a ConsoleApplication project. And I want to make a server that runs in 3 threads. I will explain in the code below.
The question is how can I invoke a function from a separate thread, or make an event on a separate thread?
This is the main server class.
public class GiNetServer
{
public void Start()
{
netServer = new NetServer();
msgHandler = new NetMsgHandler();
netServer.NewNetMsg += msgHandler.HandleMsg;
Work();
}
private void Work()
{
while(true) //This runs in the MainThread
sleep(1);
}
}
The NetServer class creates 2 Threads: acceptClientsThread and receiveMessagesThread.
The receive thread calls the NewNetMsg.
public class NetServer
{
public event NewNetMsgEventHandler NewNetMsg;
public NetServer()
{
acceptClientsThread = new Thread(ListenForClients);
receiveMessageThread = new Thread(Receive);
//and of course starts them here...
}
private void Receive()
{
while(true)
{
Heartbeat();
}
}
private void Heartbeat()
{
foreach(netClient in clientsList)
{
if (netClient.DataAvalible)
{
netClient.Recive();
}
if (!netClient.IsBufferEmpty())
{
nextMsg = netClient.NextMessage();
if (nextMsg != null)
NewNetMsg(netClient, nextMsg); //Call the event!
}
}
}
}
How can I make the msgHandler.HandleMsg function run in a separate thread or in the MainThread?
Like this, HandleMsg runs in the receiveMessagesThread.
The code above is pseudocode-ish. If there is anything ambigous please let me know.
There are a lot of different ways to move the HandleMsg call onto a different thread, depending on what your requirements are. The simplest way would be to raise the NewNetMsg event on a different thread using the ThreadPool:
ThreadPool.QueueUserWorkItem(s => NewNetMsg(netClient, nextMsg));
You could also use the Task Parallel Library (TPL). You could also add the event to a ConcurrentQueue that is processed by a dedicated background thread. And there are more options. Without more details it is impossible to give a more specific recommendation.
I am just wondering about problems involved passing a parent to child, should it be done etc, so that a child can access functionality from the parent, in this case it involves threads. My scenario follows:
public class A
{
public A()
{
B b = new B(this);
Thread thread = new Thread(new ThreadStart(b.GO));
}
public string DoSomething() { return "Something Done"; }
}
public class B
{
A _a;
public B(A a)
{
_a = a;
}
public void GO() { _a.DoSomething(); }
}
Based on above I'm wondering about any convention clashes the occur, or problems that come into effect when you do something like this, is it bad to do this? I know that there definitely brings up some thread safety issues. But my overall question is ok to do this, does it bring up some other issues? How would I update values in the main thread?
The reason why I want it separate is because class B has a timer in it(not in shown code) that when it runs out does somethings, then tells class A that it has finished, resets the timer and goes back to sleep until the timer runs out again, how would I do that otherwise?
~Regards,
Heinrich
Looking at the code, you don't appear to have any threading issues. You might introduce a race condition if you are working on the same variables, but that isn't special to the situation you propose.
You would treat this like any other multi-threaded situation and lock resources that might be accessed by multiple threads.
I would recommend the following online book: http://www.albahari.com/threading/
I don't think you really have to connect them as tightly as you are, what you are trying to do is simply pass messages or states between threads. So the reason I would recommend not having them so tightly connected is to reduce coupling.
The website I referenced contains many different signaling techniques. Pick the simplest for your needs. I would need more details about your exact requirements to pick one for you.
Another way to handle what you are doing is for B to raise an event and for A to handle the event. That way you don't have to pass A into B. I don't know what your real structure is, but lets say that B's thread function does something more complicated and A implements IDisposable. What happens if A is disposed before B gets to the point that it is calling a method on A. To me the cleaner way to handle that situation is to have B raise an event and A register for it.
public class A
{
B _b;
public A()
{
_b = new B();
_b.DidSomething += HandleDidSomething;
}
private void HandleDidSomething(object source, EventArgs e)
{
// Handle the B did something case
}
public void WaitForBToFinish() { _b.DoneDoingThings.WaitOne(); }
}
public class B
{
Event EventHandler DidSomething;
ManualResetEvent DoneDoingThings = new ManualResetEvent(false);
public B() {}
public void StartDoingThings()
{
new Thread(DoThings).Start();
}
private void DoThings()
{
for (int i=0; i < 10; i++)
{
Thread.Sleep(1000);
OnDidSomething(new EventArgs());
}
DoneDoingThings.Set();
}
private void OnDidSomething(EventArgs e)
{
if (DidSomething != null)
{
DidSomething(e);
}
}
}
Note - You should implement IDisposable in class B and dispose of the ManualResetEvent, I just am too lazy to do all that for sample code, and just wanted to give you an idea about using events to signal work was done.