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.
Related
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);
});
}
}
}
As you can see, I have two classes. RfidReaderHardware generates event in thread "th", but Form running at another thread. As you can see, in form if use Invoke method of ListViewControl. So, question is how to change RfidReaderHardware to resolve encapsulation problem.
public class RfidReaderHardware : IDisposable
{
public event EventHandler<RfidReaderEventArgs> OnNewPackage;
Thread th;
//This method will be called from thread "th"
private void FireNewPackageEvent(UHFPackage package)
{
... code ...
}
... some code ...
}
and we have example code, where this event is using
public partial class PassageForm : Form
{
RfidReaderHardware RfidReader = new RfidReaderHardware(...);
private void Form1_Load(object sender, EventArgs e)
{
RfidReader.OnNewPackage += NewRfidPackage;
}
//not sure, but i think it's running in thread "th"
private void NewRfidPackage(Object o, RfidReaderEventArgs e)
{
ListViewItem item = new ListViewItem();
//from point of encapsulation view it's wrong as you know
CPackageList.Invoke(new Action(() => {CPackageList.Items.Add(item); }));
}
}
question is how to change RfidReaderHardware to resolve encapsulation problem
In fact there is no encapsulation problem. By definition, the relation between event source and subscriber is one to many, hence the source cannot "encapsulate" a logic for a specific subscriber. It's the subscriber choice how to handle the notification. One can ignore it, or handle it immediately, or like in your case handle it on the UI thread either synchronously (using Control.Invoke) or asynchronously (using Control.BeginInvoke).
Not so sure there's any real need to fix this, having the UI object itself deal with the fact that event is fired on the "wrong" thread is not a flaw. As long as you know it is in fact fired on the wrong thread, a documentation requirement.
.NET however has a general mechanism to solve this, it is used in several places inside the .NET Framework code. Your RfidReaderHardware class constructor can copy the value of SynchronizationContext.Current and store it in a field. With the implicit assumption that the object is created by code that runs on the UI thread. When you are ready to fire the event, and the copied object isn't null, you can then use its Post() or Send() method. Which automagically makes the code resume on the UI thread. Regardless of the specific UI class library that was used, works just as well in a WPF or Universal app for example.
Some sample code, it doesn't take much:
public class RfidReaderHardware {
public event EventHandler Received;
public RfidReaderHardware() {
syncContext = System.Threading.SynchronizationContext.Current;
}
protected void OnReceived(EventArgs e) {
if (syncContext == null) FireReceived(e);
else syncContext.Send((_) => FireReceived(e), null);
}
protected void FireReceived(EventArgs e) {
var handler = Received;
if (handler != null) Received(this, e);
}
private System.Threading.SynchronizationContext syncContext;
}
I'm working on a winforms application that is very complicated, and has massive callback chains being passed around all over the place.
As an example loosely based on this code, there could be a "Manager" class, that spawns a class "SetUpWorkerThreads" class, which creates a "HandleWorker" thread for say 10 workers.
The worker thread needs to call back to the manager class on occasion, to achieve this the code looks like this:
public class Manager
{
public delegate void SomethingHappenedHandler();
private void Init()
{
var x = new SetUpWorkerThreads(SomethingHappened);
}
private void SomethingHappened()
{
// Handle something happened
}
}
public class SetUpWorkerThreads
{
private readonly Manager.SomethingHappenedHandler _somethingHappened;
public SetUpWorkerThreads(Manager.SomethingHappenedHandler somethingHappened)
{
_somethingHappened = somethingHappened;
}
public void SetupTheThreads()
{
// Contrived!
for (int x=0; x<10; x++)
{
var worker = new Worker(_somethingHappened);
new Thread(worker.DoingSomething).Start();
}
}
}
public class Worker
{
private readonly Manager.SomethingHappenedHandler _somethingHappened;
public Worker(Manager.SomethingHappenedHandler somethingHappened)
{
_somethingHappened = somethingHappened;
}
public void DoingSomething()
{
// ... Do Something
_somethingHappened();
}
}
In reality, there can be many more classes involved, each passing around a mass of callbacks for various things. I realise that poor class/application design is playing a part in this, but are there better ways to go about handling these interactions between classes, specifically in winforms apps, and when a lot of threading is going on?
I can't see that the threading makes it more or less problematic.
One alternative is to use events instead of callbacks, but that won't break up the long chains and will give you an unsubscribing hell too.
One possible approach is to create an object responsible for handling all the events. Either as a singleton or as a single object that you pass to all your threads (instead of the callbacks). Then you can have a simple interface on the EventRouter object to raise events from the threads. You can then subscribe to events on the EventRouter where you need to handle "something happened".
Edit
Something the GoF pattern Mediator but with a publisher-subscriber twist.
I have a class that is a "manager" sort of class. One of it's functions is to signal that the long running process of the class should shut down. It does this by setting a boolean called "IsStopping" in class.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
// do work...
}
}
}
Now, DoWork() was a gigantic function, and I decided to refactor it out and as part of the process broke some of it into other classes. The problem is, Some of these classes also have long running functions that need to check if isStopping is true.
public class Foo
{
bool isStoping
void DoWork() {
while (!isStopping)
{
MoreWork mw = new MoreWork()
mw.DoMoreWork() // possibly long running
// do work...
}
}
}
What are my options here?
I have considered passing isStopping by reference, which I don't really like because it requires there to be an outside object. I would prefer to make the additional classes as stand alone and dependancy free as possible.
I have also considered making isStopping a property, and then then having it call an event that the inner classes could be subscribed to, but this seems overly complex.
Another option was to create a "Process Cancelation Token" class, similar to what .net 4 Tasks use, then that token be passed to those classes.
How have you handled this situation?
EDIT:
Also consider that MoreWork might have a EvenMoreWork object that it instantiates and calls a potentially long running method on... and so on. I guess what i'm looking for is a way to be able to signal an arbitrary number of objects down a call tree to tell them to stop what they're doing and clean up and return.
EDIT2:
Thanks for the responses so far. Seems like there's no real consensus on methods to use, and everyone has a different opinion. Seems like this should be a design pattern...
You can go two ways here:
1) The solution you've already outlined: pass a signaling mechanism to your subordinate objects: a bool (by ref), the parent object itself cloaked in an interface (Foo: IController in the example below), or something else. The child objects check the signal as needed.
// Either in the MoreWork constructor
public MoreWork(IController controller) {
this.controller = controller;
}
// Or in DoMoreWork, depending on your preferences
public void DoMoreWork(IController controller) {
do {
// More work here
} while (!controller.IsStopping);
}
2) Turn it around and use the observer pattern - which will let you decouple your subordinate objects from the parent. If I were doing it by hand (instead of using events), I'd modify my subordinate classes to implement an IStoppable interface, and make my manager class tell them when to stop:
public interface IStoppable {
void Stop();
}
public class MoreWork: IStoppable {
bool isStopping = false;
public void Stop() { isStopping = true; }
public void DoMoreWork() {
do {
// More work here
} while (!isStopping);
}
}
Foo maintains a list of its stoppables and in its own stop method, stops them all:
public void Stop() {
this.isStopping = true;
foreach(IStoppable stoppable in stoppables) {
stoppable.Stop();
}
}
I think firing an event that your subclasses subscribe to makes sense.
You could create a Cancel() method on your manager class, and on each of your other worker classes. Base it on an interface.
The manager class, or classes that instantiate other worker classes, would have to propagate the Cancel() call to the objects they are composed of.
The deepest nested classes would then just set an internal _isStopping bool to false and your long-running tasks would check for that.
Alternatively, you could maybe create a context of some sort that all the classes know about and where they can check for a canceled flag.
Another option was to create a
"Process Cancelation Token" class,
similar to what .net 4 Tasks use, then
that token be passed to those classes.
I am not familiar with this, but if it is basically an object with a bool property flag, and that you pass into each class, then this seems like the cleanest way to me. Then you could make an abstract base class that has a constructor that takes this in and sets it to a private member variable. Then your process loops can just check that for cancellation.
Obviously you will have to keep a reference to this object you have passed into your workers so that it's bool flag can be set on it from your UI.
Your nested types could accept a delegate (or expose an event) to check for a cancel condition. Your manager then supplies a delegate to the nested types that checks its own "shouldStop" boolean. This way, the only dependency is of the ManagerType on the NestedType, which you already had anyway.
class NestedType
{
// note: the argument of Predicate<T> is not used,
// you could create a new delegate type that accepts no arguments
// and returns T
public Predicate<bool> ShouldStop = delegate() { return false; };
public void DoWork()
{
while (!this.ShouldStop(false))
{
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private bool checkShouldStop(bool ignored)
{
return shouldStop;
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.ShouldStop = checkShouldStop;
nestedType.DoWork();
}
}
You could abstract this behavior into an interface if you really wanted to.
interface IStoppable
{
Predicate<bool> ShouldStop;
}
Also, rather than just check a boolean, you could have the "stop" mechanism be throwing an exception. In the manager's checkShouldStop method, it could simply throw an OperationCanceledException:
class NestedType
{
public MethodInvoker Stop = delegate() { };
public void DoWork()
{
while (true)
{
Stop();
// do work here
}
}
}
class ManagerType
{
private bool shouldStop = false;
private void checkShouldStop()
{
if (this.shouldStop) { throw new OperationCanceledException(); }
}
public void ManageStuff()
{
NestedType nestedType = new NestedType();
nestedType.Stop = checkShouldStop;
nestedType.DoWork();
}
}
I've used this technique before and find it very effective.
Litter your code with statements like this wherever it is most sensible to check the stop flag:
if(isStopping) { throw new OperationCanceledException(); }
Catch OperationCanceledException right at the top level.
There is no real performance penalty for this because (a) it won't happen very often, and (b) when it does happen, it only happens once.
This method also works well in conjunction with a WinForms BackgroundWorker component. The worker will automatically catch a thrown exception in the worker thread and marshal it back to the UI thread. You just have to check the type of the e.Error property, e.g.:
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if(e.Error == null) {
// Finished
} else if(e.Error is OperationCanceledException) {
// Cancelled
} else {
// Genuine error - maybe display some UI?
}
}
You can flatten your call stack by turning each DoWork() call into a command using the Command pattern. At the top level, you maintain a queue of commands to perform (or a stack, depending on how your commands interact with each other). "Calling" a function is translated to enqueuing a new command onto the queue. Then, between processing each command, you can check whether or not to cancel. Like:
void DoWork() {
var commands = new Queue<ICommand>();
commands.Enqueue(new MoreWorkCommand());
while (!isStopping && !commands.IsEmpty)
{
commands.Deque().Perform(commands);
}
}
public class MoreWorkCommand : ICommand {
public void Perform(Queue<ICommand> commands) {
commands.Enqueue(new DoMoreWorkCommand());
}
}
Basically, by turning the low-level callstack into a data structure you control, you have the ability to check stuff between each "call", pause, resume, cancel, etc..
I have a layered worker class that I'm trying to get progress reports from. What I have looks something like this:
public class Form1
{
private void Start_Click()
{
Controller controller = new Controller();
controller.RunProcess();
}
}
public class Controller
{
public void RunProcess()
{
Thread newThread = new Thread(new ThreadStart(DoEverything));
newThread.Start();
}
private void DoEverything()
{
// Commencing operation...
Class1 class1 = new Class1();
class1.DoStuff();
Class2 class2 = new Class2();
class2.DoMoreStuff();
}
}
public class Class1
{
public void DoStuff()
{
// Doing stuff
Thread.Sleep(1000);
// Want to report progress here
}
}
public class Class2
{
public void DoMoreStuff()
{
// Doing more stuff
Thread.Sleep(2000);
// Want to report progress here as well
}
}
I've used the BackgroundWorker class before, but I think I need something a bit more free form for something like this. I think I could use a delegate/event solution, but I'm not sure how to apply it here. Let's say I've got a few labels or something on Form1 that I want to be able to update with class1 and class2's progress, what's the best way to do that?
Using events is the most straightforward solution. When you subscribe to the event from the main thread, the handler should check the Control.IsInvokeRequired to know whether it must call itself again through Invoke(...) to get the message passed to the right thread.
John is correct. You want to utilize events and for that you'll need to use a delegate or delegates. This might give you some ideas.
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
If you do not want to block the processing threads during notification, you can use Control.BeginInvoke() for fire & forget behavior.
To decrease the number of calls and update progress on a regular interval, you may want to encapsulate the states of different operations in classes.
This way you can just write states to e.g. volatile fields - of presumably another, aggregate-state class - and use a timer on the GUI thread to re-read state and refresh labels accordingly.