WCF Async Calls Polling or Flagging - Best Practice - c#

I'm working on this Silverlight 3.0 Project that is completely filled with Async Calls to a Web Service. At the Main Page it fetches some needed data in order for the application to work correctly using 3 Async Calls. Right now the application does not disable any controls while executing those calls meaning a user can interact with it without that needed data. I need to disable the whole grid and only after all 3 Async calls are finished then and only then enable the grid.
What's the best practice for doing this.
These are my calls:
client.GetAllAsync();
client.GetAllCompleted += new EventHandler<GetAllCompletedEventArgs>(client_GetAllCompleted);
client.GetActualAsync();
client.GetActualCompleted += new EventHandler<GetActualCompletedEventArgs>(client_GetActualCompleted);
client.GetSomeAsync();
client.GetSomeCompleted += new EventHandler<GetSomeCompletedEventArgs>(client_GetSomeCompleted);

Seems lot a lot of work just to queue some user interactivity.
I typically provide an application-wide interface:
public interface IAppGlobalState
{
void BeginAsync();
void EndAsync();
}
In the implementation, I'll do this:
public partial class MainShell : UserControl, IAppGlobalState
{
private int _queue;
private object _mutex = new Object();
public void BeginASync()
{
Monitor.Enter(_mutex);
if (_queue++ == 0)
{
VisualStateManager.GoToState(this, "BusyState", true);
}
Monitor.Exit(_mutex);
}
public void EndAsync()
{
Monitor.Enter(_mutex);
if (--_queue == 0)
{
VisualStateManager.GoToState(this, "IdleState", true);
}
Monitor.Exit(_mutex);
}
}
Of course if you have heavy multi-threading then you'll use Interlocked on those but most of the time you'll be invoking it from the same thread. Then, you simply do:
GlobalState.BeginAsync();
client.FirstAsyncCall();
GlobalState.BeginAsync();
client.FirstAsyncCall();
And then on the return, just:
GlobalState.EndAsync();
If you have nested calls, no problem, this method unwinds them.

Make a unit of work item in your silverlight
This UOW raises an event when finished
Bind that event to your GUI code
Use signaling or a simple counter in your unit of work to raise the 'finished' event.

Related

Declaring Thread in a Constructor in C#

I´m currently figuring out threads and how to work with them.
At the same time Im working on my understanding on Events/Global Events (just for context).
I defined a thread inside a object with the function the thread will use on thread.Start().
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(Thread testthread, EventWaitHandle globalEvent)
{
this.testthread = testthread;
this.globalEvent = globalEvent;
}
public void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
So now, like in this example in a Windows Forms App, Im trying to set an instance of this class while setting the instance of the thread at the same time (with the work method the should run later on).
Im struggling with this part here.
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(new Thread(ProblemHere), globalEvent);
threadClass.Execute();
}
This is a button which starts the thread with the work its supposed to do.
The variable threadClass is just the initialization in the forms1.cs:
Name threadClass;
I know that it wants a delegate to pass the method which the thread should use on start.
I tried pretty much anything I found and cant make it work.
I cant just pass the method, that doesnt work.
And the stuff I found in the c# documentation is pretty much just passing the method, as far as I understood it.
Which is propably wrong.
And I just noticed, how am I able to actually call on that property/thread.start if its only created on runtime?
Not a full solution, but a bump to get you going:
What I would suggest is a little refactor like this
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(EventWaitHandle globalEvent)
{
this.testthread = new Thread(Execute); // Creates a Thread, that is directed to execute `Execute`
this.globalEvent = globalEvent;
this.testthread.Start(); // Tells the framework to schedule the thread for execution.
}
private void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
And in the Button handler just do
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(globalEvent);
}
Mind that there are still a good portion of mistakes and ooopsies, but at least, this will keep your GUI thread running and you may gain an understanding to go on from here.
A totally different approach (if you are willing to consider it) would be to use a System.Windows.Forms.Timer instead. With that you can have a method called every X time, which would check the state of the globalevent as you are trying to get the thread to doing. The timer, however, makes this a little more convenient.
The typical way would be to create the thread in the constructor, as described in the answer by Fildor.
But I want to point out that using the Thread object directly is rarely the correct way to do things since there are other tools more suited for whatever you are tryibng to do:
If you want to do something compute heavy on a background thread once, and update the UI after it has been done. Use Task.Run and async/await
If you want to do something every X seconds. Use a timer. There are both timers that run on the main thread or a background thread, see differences between timers.
If you want to run an compute heavy operation in parallel, use Parallel.For, possibly in combination with Task.Run.
If you want to call IO intensive methods without freezing the UI, use async/await in combination with the appropriate Async methods.
If you want to create a producer/consumer or other processing pipeline there is the DataFlow library

Why is UI unresponsive while being programmatically controlled?

I hand-rolled a MVC-style implementation of a game that I want to autoplay. By "autoplay" I mean that the buttons that normally a user would click while playing I want a controller to automatically initiate. That way I can watch the game play itself for quality control reasons. This particular game has a lot of code, so instead of providing it as an example I've created a silly HelloWorld example using the same approach.
Before I provide the example, here is my issue: everything you see below is functional, and "works"; except for one thing: I'm unable to shut-off the autoplay because the UI becomes unresponsive and the button to turn it off won't respond to a click event.
First create a .Net 4.6.1 winforms project in a solution. (.net version probably doesn't matter as long as it is >= 4.5). Create a Form that looks like this:
In the code behind, copy paste this: (change names as needed to compile)
using System;
using System.Threading;
using System.Windows.Forms;
namespace WinformsExample
{
public partial class HelloWorldView : Form
{
private readonly HelloWorldController MyHelloWorldController;
public HelloWorldView()
{
InitializeComponent();
MyHelloWorldController = new HelloWorldController();
}
private void button1_Click(object sender, EventArgs e)
{
MyHelloWorldController.HelloWorldRequested();
if (MyHelloWorldController.IsAutomated)
{
Thread.Sleep(2000);
button1.PerformClick();
}
}
private void HelloWorldView_Load(object sender, EventArgs e)
{
MyHelloWorldController.HelloWorldRequestedEvent += OnHelloWorldRequested;
}
private void OnHelloWorldRequested(HelloWorldParameters parameters)
{
textBox1.Text += parameters.HelloWorldString + Environment.NewLine;
textBox1.Update();
}
private void button2_Click(object sender, EventArgs e)
{
MyHelloWorldController.IsAutomated = !MyHelloWorldController.IsAutomated;
if (MyHelloWorldController.IsAutomated)
{
button2.Text = "hello world - is on";
button2.Update();
button1.PerformClick();
}
else
{
button2.Text = "hello world - is off";
button2.Update();
}
}
}
}
And create a class titled HelloWorldController.cs and copy paste this in to it:
namespace WinformsExample
{
public class HelloWorldParameters
{
public string HelloWorldString { get; set; }
}
public delegate void HelloWorldEventHandler(HelloWorldParameters parameters);
public class HelloWorldController
{
private readonly HelloWorldParameters _parameters;
public event HelloWorldEventHandler HelloWorldRequestedEvent;
public bool IsAutomated { get; set; }
public HelloWorldController()
{
_parameters = new HelloWorldParameters();
}
public void HelloWorldRequested()
{
_parameters.HelloWorldString = "Hello world!!";
if (HelloWorldRequestedEvent != null)
HelloWorldRequestedEvent(_parameters);
}
}
}
...go ahead and rename things if you need to. Now build the program. Click the first button. You will see "hello world". Now click the second button, you will see "hello world" printed every 2 seconds.
The way I thought this would work is that by clicking button2 a second time, that it would stop the autoplay. However, the UI is unresponsive and the button click event never happens.
What is going on here that is causing the UI to be unresponsive and how can I fix it so that I get the intended behavior?
*UPDATE - HERE IS THE SOLUTION *
Keep everything the same as above except for HelloWorldView.cs. Remove the call to Thread.Sleep(). Drag and drop a timer from the toolbox to the design surface. You will see an icon on the bottom of the designer surface labeled
timer1
Copy paste the following code in to HelloWorldView.cs. Compile and execute. If everything is correct you should be able to turn on and off the "hello world" display by clicking the button at any time - the UI stays responsive.
using System;
using System.Windows.Forms;
namespace WinformsExample
{
public partial class HelloWorldView : Form
{
private readonly HelloWorldController MyHelloWorldController;
public HelloWorldView()
{
InitializeComponent();
MyHelloWorldController = new HelloWorldController();
}
private void onTimerTick(object sender, EventArgs e)
{
button1.PerformClick();
}
private void OnHelloWorldRequested(HelloWorldParameters parameters)
{
textBox1.Text += parameters.HelloWorldString + Environment.NewLine;
textBox1.Update();
}
private void HelloWorldView_Load(object sender, EventArgs e)
{
MyHelloWorldController.HelloWorldRequestedEvent += OnHelloWorldRequested;
}
private void button1_Click(object sender, EventArgs e)
{
MyHelloWorldController.HelloWorldRequested();
}
private void button2_Click(object sender, EventArgs e)
{
MyHelloWorldController.IsAutomated = !MyHelloWorldController.IsAutomated;
if (MyHelloWorldController.IsAutomated)
{
button2.Text = "hello world - is on";
button2.Update();
timer1.Interval = 2000;
timer1.Tick += onTimerTick;
timer1.Start();
}
else
{
timer1.Stop();
button2.Text = "hello world - is off";
button2.Update();
}
}
}
}
WinForms uses a single message pump thread (called the UI thread). (If you are unfamiliar with the concept you should research Windows messages and Windows message pump).
Thread.Sleep causes the currently executing thread the sleep, or pause, for a time. This sleep/pause is like death to the thread - it is aware of nothing and unable to do anything.
As the currently executing thread in a WinForms app is usually the UI thread - Thread.Sleep will cause the UI to become unresponsive because it is no longer able to pump messages.
An alternative design would be to use a form-based Timer. Place your game playing code in the Timer's Tick event.
What is going on here that is causing the UI to be unresponsive and how can I fix it so that I get the intended behavior?
There are essentially two reasons why your app becomes unresponsive.
1. Thread.Sleep() in UI thread
GUI applications on Windows are generally driven by messages (mouse clicks; keyboard; screen drawing) posted to it which are placed on a queue. The UI thread processes these messages one by one dispatching the message to the appropriate handler. In this way it is known as the Message Pump. If during processing one of these messages too much time elapses, then the UI will appear to freeze. Event handlers should be as fast as possible.
During your click handlers you are using Thread.Sleep(2000); which will prevent the UI thread from updating the UI of your application, in essence simulating an event handler that takes far too long to process an event. It is perhaps no different to say performing a lengthy database or WCF operation on the UI thread, hence why people tend to put such calls on a separate thread or task.
Recommend you remove the Thread.Sleep and replace it with a timer as others have indicated.
2. Infinite Recursive Loop on button1 handler
When you click button2 for the first time, the click handler for button2 is invoked where automation is enabled. You then simulate button1 being clicked via button1.PerformClick();.
During the call to button1.PerformClick, the click handler for button1 button1_Click() is invoked. It is there that you sleep for 2 seconds (which isn't healthy for the UI) but the secondary problem is that you immediately call button1.PerformClick(); from inside the button1 click handler, in essence setting up an infinite recursive loop.
If you were to remove the Thread.Sleep(2000) your app will eventually lead to a StackOverflowException. Your code as it stands now (even with the sleep) will still overflow, it's just that it will take much longer to become apparent.
Again, consider replacing it with a timer.
3. Exclusivity
It's important to note that ignoring the stack fault for a moment, the design is such that your app can't do anything else whilst this infinite loop is running. So if your game had other buttons to click; scores to display; sound effects to play; all from the point of view of the button2 handler, most likely it will never happen because it is too busy exclusively processing button1.
Conclusion
Keep UI responsive: Avoid Thread.Sleep() in your code
Avoid recursion: Don't use PerformClick() for a button whilst you are inside the click handler for said button
Your "Thread.Sleep()" call puts the UI thread to sleep. Use a Timer instead. Then terminate the Timer on the second press. (You could also do this with Tasks, if you want to use another thread you need to make the 2 threads communicate in someway so that the UI thread is the only one actually updating the UI)
Desktop applications have a so called UI thread. It's basically an infinite loop which keeps checking if something happened, such as a mouse click, and redraws the window if needed. Coding in WinAPI you would need to write this loop yourself, WinForms and other UI frameworks hide it away. But your click handler is called from inside this loop. So if your code takes too much time - like, because you call Thread.Sleep inside - the loop will not continue and will not be able to process anything that is happening to the application. This why long-running processes need to take place on a separate thread.
As others have said, you are blocking the UI thread with the Thread.Sleep and recursive button1.PerformClick(); call. You have to let the UI run as freely as possible and let it go idle quickly.
So, just for the fun of it I have rewritten your code to do just that. I've also implemented it with Microsoft's Reactive Extensions (Rx) - just NuGet "Rx-WinForms" to get the bits. Rx allows you to do some very funky things that you can't easily do with events.
Here's your form now:
public partial class HelloWorldView : Form
{
private readonly HelloWorldController MyHelloWorldController =
new HelloWorldController("Hello world!!", TimeSpan.FromSeconds(1.0));
public HelloWorldView()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MyHelloWorldController.Messages
.ObserveOn(this)
.Subscribe(message =>
{
textBox1.Text += message + Environment.NewLine;
});
MyHelloWorldController.IsAutomateds
.ObserveOn(this)
.Subscribe(isAutomated =>
{
button2.Text = "hello world - is " + (isAutomated ? "on" : "off");
});
}
private void button1_Click(object sender, EventArgs e)
{
MyHelloWorldController.Trigger();
}
private void button2_Click(object sender, EventArgs e)
{
MyHelloWorldController.IsAutomated = !MyHelloWorldController.IsAutomated;
}
}
You'll notice that I've simplified down the UI. It really does as little as possible to update itself and to notify the HelloWorldController of its actions.
The worst part of the code are the two .Subscribe calls in Form1_Load. These are simply looking at the two observables (Rx's version of events if you like) and makes sure the events are run on the UI thread with the .ObserveOn(this) call, and then they subscribe to values produced from the HelloWorldController.
The UI is simply updating itself from the controller and telling the controller what it is doing. There is virtually no logic being performed in the UI. This is how it should be with any MVC-style coding.
Now the HelloWorldController is where the fun is.
It starts off pretty simply:
private string _message;
private TimeSpan _automatedPeriod;
public HelloWorldController(string Message, TimeSpan automatedPeriod)
{
_message = Message;
_automatedPeriod = automatedPeriod;
}
This is basically the information about what message to send to the UI and how often when the controller is automating the values.
It then tracks whether it is automated or not:
private bool _isAutomated = false;
Now it contains the Rx observables - these are like the events you were using.
private Subject<string> _messages = new Subject<string>();
public IObservable<string> Messages { get { return _messages.AsObservable(); } }
private Subject<bool> _isAutomateds = new Subject<bool>();
public IObservable<bool> IsAutomateds { get { return _isAutomateds.AsObservable(); } }
private SerialDisposable _serialSubscription = new SerialDisposable();
In Rx an IObservable<T> is something I can subscribe to to get a series of values - just like an event. The Subject<T> is something that I can manually push values into, but it also can be an IObservable<T> that can be subscribed to. It's the pair of these that lets me raise events. Think of the Subject<string> to be the equivalent of the HelloWorldRequested method in your code and the IObservable<string> to be the equivalent of the HelloWorldRequestedEvent event.
If I call _messages.OnNext("Hello") then any subscribers to IObservable<string> Messages would get a "Hello" sent to them. Just like an event.
IsAutomated looks like this:
public bool IsAutomated
{
get { return _isAutomated; }
set
{
_isAutomated = value;
_isAutomateds.OnNext(value);
if (_isAutomated)
{
this.Trigger();
}
}
}
So it does its job of updating its own internal state, but it also calls _isAutomateds.OnNext(value) to push out the updates to any subscribers of IObservable<bool> IsAutomateds. It also works out if it needs to trigger the controller to produce messages with the this.Trigger() call.
Finally the Trigger method looks like this:
public void Trigger()
{
if (_isAutomated)
{
_serialSubscription.Disposable =
Observable
.Interval(_automatedPeriod)
.StartWith(0)
.TakeUntil(_isAutomateds.Where(x => x == false))
.Subscribe(n => _messages.OnNext(_message));
}
else
{
_messages.OnNext(_message);
}
}
The easy part of this is when the _isAutomated is false then it simply sends one message out via the _messages.OnNext(_message) call.
When _isAutomated is true it uses some of the coolness of Rx to set up effectively a timer to produce values every TimeSpan _automatedPeriod. From your code you wanted every 2 seconds so the TimeSpan would be TimeSpan.FromSeconds(2.0).
Observable.Interval(_automatedPeriod) defines a timer that begins producing values after the first period of time and then every period of time between.
So the .StartWith(0) says that it should immediately produce a value when it is subscribed to.
The .TakeUntil(_isAutomateds.Where(x => x == false)) is the best part here - it says that it will take the values from the the Observable.Interval(_automatedPeriod).StartWith(0) and stop when it gets a value from _isAutomateds.Where(x => x == false) - in other words when the IsAutomated is set to false.
The .Subscribe(n => _messages.OnNext(_message)); simply pushes a value to the _messages subject so that all subscribers of IObservable<string> Messages gets their messages.
Just put all of the HelloWorldController I've given you in public class HelloWorldController { ... } and you're good to go.
The works I think like it should and shows how lightweight the UI code can be.
I hope you find this worth playing with.
You'll need to add these using's to the top of your code to get all of the code to compile:
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;

How to I design a class so looping is not necessary?

I have to process some records. For reasons that are unnecessary to mention, I can not loop through these records at the UI layer. The client wants to be able to simply call the middle tier using a function call, have the middle tier loop through and process the records. The problem is they want the middle tier to report back a status after each record is processed. How would I design that. For what it's worth, this is c# in .net.
A setup similar to this should work. It's untested/uncompiled so consider it pseudo-code. Also, it should ideally be asynchronous, but this will give you a starting point as an example of how to communicate changes back to the UI through eventing without the UI being aware of any "looping".
Event plumbing:
public class MyEventArgs : EventArgs
{
//add properties you want to send to the UI here.
}
public delegate void ProcessedEventHandler(object sender, MyEventArgs e);
Middle tier raises events.
public class MiddleTier
{
public event ProcessedEventHandler RecordProcessed;
//NOTE it would be best to make a tweak to do this asynchronously
//such that all records can be processed at the same time instead
//of processing them sequentially. if the method were async, you
//could do all of this without the method itself blocking.
public void Process()
{
//this loop/processing should ideally be asynchronous
foreach(var thing in whatever)
{
//process thing
//make event args
var args = new MyEventArgs(); //fill out properties
//raise event
OnProcessed(args);
}
private void OnProcessed(MyEventArgs args)
{
//follow this pattern for thread safety
var p = RecordProcessed;
if(p != null)
p(this, args);
}
}
}
Then in your UI layer:
//in some UI function
var mt = new MiddleTier();
//handle event
mt.RecordProcessed +=
(s, args) =>
{
//update UI
};
//kick things off
mt.Process();
You don't mention what technology your UI will be but assuming it is an application, you want the processing to happen on a separate thread so as to allow your UI to update.
I would look at the backgroundworker component as a starting point. It facilitates a progresschanged event you can use to notify your UI of how it getting on. Similar can be achieved using asynchronous framework.

Synchronization mechanism for an observable object

Let's imagine we have to synchronize read/write access to shared resources. Multiple threads will access that resource both in read and writing (most of times for reading, sometimes for writing). Let's assume also that each write will always trigger a read operation (object is observable).
For this example I'll imagine a class like this (forgive syntax and style, it's just for illustration purposes):
class Container {
public ObservableCollection<Operand> Operands;
public ObservableCollection<Result> Results;
}
I'm tempted to use a ReadWriterLockSlim for this purpose moreover I'd put it at Container level (imagine object is not so simple and one read/write operation may involve multiple objects):
public ReadWriterLockSlim Lock;
Implementation of Operand and Result has no meaning for this example.
Now let's imagine some code that observes Operands and will produce a result to put in Results:
void AddNewOperand(Operand operand) {
try {
_container.Lock.EnterWriteLock();
_container.Operands.Add(operand);
}
finally {
_container.ExitReadLock();
}
}
Our hypotetical observer will do something similar but to consume a new element and it'll lock with EnterReadLock() to get operands and then EnterWriteLock() to add result (let me omit code for this). This will produce an exception because of recursion but if I set LockRecursionPolicy.SupportsRecursion then I'll just open my code to dead-locks (from MSDN):
By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks.
I repeat relevant part for clarity:
Recursion [...] makes your code more prone to deadlocks.
If I'm not wrong with LockRecursionPolicy.SupportsRecursion if from same thread I ask a, let's say, read lock then someone else asks for a write lock then I'll have a dead-lock then what MSDN says makes sense. Moreover recursion will degrade performance too in a measurable way (and it's not what I want if I'm using ReadWriterLockSlim instead of ReadWriterLock or Monitor).
Question(s)
Finally my questions are (please note I'm not searching for a discussion about general synchronization mechanisms, I would know what's wrong for this producer/observable/observer scenario):
What's better in this situation? To avoid ReadWriterLockSlim in favor of Monitor (even if in real world code reads will be much more than writes)?
Give up with such coarse synchronization? This may even yield better performance but it'll make code much more complicated (of course not in this example but in real world).
Should I just make notifications (from observed collection) asynchronous?
Something else I can't see?
I know that there is not a best synchronization mechanism so tool we use must be right one for our case but I wonder if there are some best practice or I just ignore something very important between threads and observers (imagine to use Microsoft Reactive Extensions but question is general, not tied to that framework).
Possible solutions?
What I would try is to make events (somehow) deferred:
1st solution
Each change won't fire any CollectionChanged event, it's kept in a queue. When provider (object that push data) has finished it'll manually force the queue to be flushed (raising each event in sequence). This may be done in another thread or even in the caller thread (but outside the lock).
It may works but it'll make everything less "automatic" (each change notification must be manually triggered by producer itself, more code to write, more bugs all around).
2nd solution
Another solution may be to provide a reference to our lock to the observable collection. If I wrap ReadWriterLockSlim in a custom object (useful to hide it in a easy to use IDisposable object) I may add a ManualResetEvent to notify that all locks has been released in this way collection itself may rise events (again in the same thread or in another thread).
3rd solution
Another idea could be to just make events asynchronous. If event handler will need a lock then it'll be stopped to wait it's time frame. For this I worry about the big thread amount that may be used (especially if from thread pool).
Honestly I don't know if any of these is applicable in real world application (personally - from users point of view - I prefer second one but it implies custom collection for everything and it makes collection aware of threading and I would avoid it, if possible). I wouldn't like to make code more complicated than necessary.
This sounds like quite the multi-threading pickle. It's quite challenging to work with recursion in this chain-of-events pattern, whilst still avoiding deadlocks. You might want to consider designing around the problem entirely.
For example, you could make the addition of an operand asynchronous to the raising of the event:
private readonly BlockingCollection<Operand> _additions
= new BlockingCollection<Operand>();
public void AddNewOperand(Operand operand)
{
_additions.Add(operand);
}
And then have the actual addition happen in a background thread:
private void ProcessAdditions()
{
foreach(var operand in _additions.GetConsumingEnumerable())
{
_container.Lock.EnterWriteLock();
_container.Operands.Add(operand);
_container.Lock.ExitWriteLock();
}
}
public void Initialize()
{
var pump = new Thread(ProcessAdditions)
{
Name = "Operand Additions Pump"
};
pump.Start();
}
This separation sacrifices some consistency - code running after the add method won't actually know when the add has actually happened and maybe that's a problem for your code. If so, this could be re-written to subscribe to the observation and use a Task to signal when the add completes:
public Task AddNewOperandAsync(Operand operand)
{
var tcs = new TaskCompletionSource<byte>();
// Compose an event handler for the completion of this task
NotifyCollectionChangedEventHandler onChanged = null;
onChanged = (sender, e) =>
{
// Is this the event for the operand we have added?
if (e.NewItems.Contains(operand))
{
// Complete the task.
tcs.SetCompleted(0);
// Remove the event-handler.
_container.Operands.CollectionChanged -= onChanged;
}
}
// Hook in the handler.
_container.Operands.CollectionChanged += onChanged;
// Perform the addition.
_additions.Add(operand);
// Return the task to be awaited.
return tcs.Task;
}
The event-handler logic is raised on the background thread pumping the add messages, so there is no possibility of it blocking your foreground threads. If you await the add on the message-pump for the window, the synchronization context is smart enough to schedule the continuation on the message-pump thread as well.
Whether you go down the Task route or not, this strategy means that you can safely add more operands from an observable event without re-entering any locks.
I'm not sure if this is exactly the same issue but when dealing with relatively small amounts of data (2k-3k entries), I have used the below code to facilitate cross thread read/write access to collections bound to UI. This code originally found here.
public class BaseObservableCollection<T> : ObservableCollection<T>
{
// Constructors
public BaseObservableCollection() : base() { }
public BaseObservableCollection(IEnumerable<T> items) : base(items) { }
public BaseObservableCollection(List<T> items) : base(items) { }
// Evnet
public override event NotifyCollectionChangedEventHandler CollectionChanged;
// Event Handler
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
// Be nice - use BlockReentrancy like MSDN said
using (BlockReentrancy())
{
if (CollectionChanged != null)
{
// Walk thru invocation list
foreach (NotifyCollectionChangedEventHandler handler in CollectionChanged.GetInvocationList())
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
// If the subscriber is a DispatcherObject and different thread
if (dispatcherObject != null && dispatcherObject.CheckAccess() == false)
{
// Invoke handler in the target dispatcher's thread
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e);
}
else
{
// Execute handler as is
handler(this, e);
}
}
}
}
}
}
I have also used the code below (which inherits from the above code) to support raising the CollectionChanged event when items inside the collection raise the PropertyChanged.
public class BaseViewableCollection<T> : BaseObservableCollection<T>
where T : INotifyPropertyChanged
{
// Constructors
public BaseViewableCollection() : base() { }
public BaseViewableCollection(IEnumerable<T> items) : base(items) { }
public BaseViewableCollection(List<T> items) : base(items) { }
// Event Handlers
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var arg = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender);
base.OnCollectionChanged(arg);
}
protected override void ClearItems()
{
foreach (T item in Items) { if (item != null) { item.PropertyChanged -= ItemPropertyChanged; } }
base.ClearItems();
}
protected override void InsertItem(int index, T item)
{
if (item != null) { item.PropertyChanged += ItemPropertyChanged; }
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
if (Items[index] != null) { Items[index].PropertyChanged -= ItemPropertyChanged; }
base.RemoveItem(index);
}
protected override void SetItem(int index, T item)
{
if (item != null) { item.PropertyChanged += ItemPropertyChanged; }
base.SetItem(index, item);
}
}
Cross-Thread Collection Synchronization
Putting a ListBox binding to a ObservableCollection , when the data changes , you update the ListBox because INotifyCollectionChanged implemented .
The defect dell'ObservableCollection is that the data can be changed only by the thread that created it.
The SynchronizedCollection does not have the problem of Multi-Thread but does not update the ListBox because it is not implemented INotifyCollectionChanged , even if you implement INotifyCollectionChanged , CollectionChanged (this, e) can only be called from the thread that created it .. so it does not work.
Conclusion
-If you want a list that is autoupdated mono-thread use ObservableCollection
-If you want a list that is not autoupdated but multi-threaded use SynchronizedCollection
-If you want both, use Framework 4.5, BindingOperations.EnableCollectionSynchronization and ObservableCollection () in this way :
/ / Creates the lock object somewhere
private static object _lock = new object () ;
...
/ / Enable the cross acces to this collection elsewhere
BindingOperations.EnableCollectionSynchronization ( _persons , _lock )
The Complete Sample
http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux

MVP with Background Worker (Exception raised)

I'm having some trouble with my MVP solution, probably threading related. I'm running Compact Framework 3.5 and using C#. I can use OpenNETCF, so BackgroundWorker is available to me.
I have a piece of code (MyClient) that connects to a web server using sockets. Code connects to the server and downloads the data (endlessly, its a stream) until the user stops it. Because the downloading of data is endless it must be run in a thread, and I think this is where I get issues.
The MyClient object has an state, represented as an enum On, Off, Connecting.
Edit - Just to clarify, when MyClient.Start() is called it connects to the server. It then takes that connection and saves it for use in the Thread run to constantly download data. So when Stop() is called it just needs to get a bool flag to tell the thread used inside MyClient to Stop. Shortened version below for clarity.
public void Start()
{
//...
//Code to Connect to server...
stream = _connection.GetStream();
//...
//Code to send/receive data to confirm connection...
State = State.On;
//Start thread to read data constantly until stopped by user setting "_continueReadingData = false"
_continueReadingData = true;
Thread readData = new Thread(ReadData);
readData.IsBackground = true;
readData.Start();
//Note readData uses the stream variable saved above
}
View calls presenter with _presenter.TurnOn();. Presenter calls model with _model.Start();. The idea is the MyClient code is started, reports its status changes and runs endless in the background until the user clicks stop. The View is protected with Invoke/BeginInvoke calls on the UI components.
I've attached a code sample of my model below. Originally I used a normal thread and got it working, as you can see below it is commented out. Two issues here, the need to use Invoke to marshall back to the UI thread for everything that reaches the view, and also The issue here is any exceptions raised don't return to the UI thread, so instead cannot be handled and will crash the application. These are the two issues I am trying to address.
I've since tried the BackgroundWorker (available in OpenNETCF, just like the normal BackgroundWorker in .Net 2.0 onwards), to handle exceptions and marshalling as in code below. But with this I can't get it to work. Instead when State is changed and reported back to the GUI. Although Invoke is called, it complains with InvalidOperationException - "Invoke or BeginInvoke cannot be called on a control until the window handle has been created". Doing some research it almost sounds like the thread is creating its own set of controls. At this point I am confused.
Can anyone lend a hand to show me how to properly start/end the threads in the model so they run in the background, raise exceptions back to the model to be handled, and marshall execution back to the UI thread so you don't have to use Invoke on every control. I'm sure it must be possible.
public class Model
{
public event EventHandler DataChanged;
public event EventHandler ErrorRaised;
private MyClient _client = new MyClient();
public Model()
{
//Register to events
_client.StateChanged += ClientStateChanged;
//Setup current values
State = _client.State;
}
void ClientStateChanged(NTRIPClient client, NTRIPState newState)
{
State = newState;
}
private State _state;
public State State
{
get { return _state; }
set
{
if (_state != value)
{
_state = value;
if (DataChanged != null)
{
DataChanged(this, EventArgs.Empty);
}
}
}
}
public void Start()
{
//Thread thread = new Thread(_NTRIPClient.Start);
//thread.IsBackground = true;
//thread.Start();
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += _client.Start();
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
{
if (ErrorRaised != null)
{
ErrorRaised(this, new ErrorEventArgs(e.Error));
}
}
}
}
The problem turned out to be that the presenter was being created in the View, which in turn created the model. This model was called before the view was completely built and thus the controls were not yet created.
A big question due to a simple mistake :)

Categories

Resources