Updating observable collection from background thread + WPF + silent update - wpf

I am planning to have a threadsafe observable collection, where in I run a task on the background and update the UI as and when result is obtained using the dispatcher.
I got a download from the internet which is ThreadSafe. But I have a small concern. I wish to do a silent update on the UI. Since the user is already working or selecting the bound collection, I would not want to disturb the user selected entry. In other words, I would like to add an entry similar to Microsoft Outlook, when a new mail arrives.
Is this possible, and are there any such examples.
Thanks

You can have derived class from ObservableCollection and override it OnCollectionChanged function and raise it handler when ever you require. follows are code.
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
private bool suspendCollectionChangeNotification;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!this.suspendCollectionChangeNotification)
{
NotifyCollectionChangedEventHandler eventHandler = CollectionChanged;
if (eventHandler != null)
{
Delegate[] delegates = eventHandler.GetInvocationList();
// Walk through invocation list
bool isEventInvoked = false;
foreach (NotifyCollectionChangedEventHandler handler in delegates)
{
isEventInvoked = false;
if (handler.Target is DispatcherObject)
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
// This check is to make sure if the call on a different thread than the dispatcher.
if (dispatcherObject != null && dispatcherObject.CheckAccess() == false)
{
// Invoke handler in the target dispatcher's thread
// Intentionally called begin invoke because there is a problem with Dispatcher.Invoke that it hangs when
// called simultaneously
dispatcherObject.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, handler, this, e);
isEventInvoked = true;
}
}
if (!isEventInvoked)
{
handler(this, e);
}
}
}
}
}

Related

IWeakEventListener.ReceiveWeakEvent() called multiple times when PropertyChanged(null) is called on source object

I'm using the PropertyObserver class in my code to avoid doing string comparisons in PropertyChanged event handling and factor out the handling of null or string.Empty as its argument (Which indicates that all properties of an object has changed).
This class uses PropertyChangedEventManager to register callbacks in the target object and implements IWeakEventListener to respond every time PropertyChanged event is invoked on the source object.
But during the creation of a unit test I found out that the IWeakEventListener.ReceiveWeakEvent() is called N number of times, with N as the number of the registered callbacks. This only occurs when null or string.Empty is specified, not when a valid property name is given in the PropertyChanged event.
Does anyone knows why this is happening and how to fix it? My goal is to do a foreach of the registered handlers ONE time when null is given, so I can update my target object by getting all the properties of the source object. But when ReceiveWeakEvent() is called N times then the foreach will be repeated N times!
To illustrate it, the following is a simplified version of the PropertyObserver class and the source class (I'm using MVVM Light's ObservableObject for INotifyPropertyChanged implementation):
public class PropertyObserver : IWeakEventListener {
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) {
if (managerType == typeof(PropertyChangedEventManager)) {
string propertyName = ((PropertyChangedEventArgs)e).PropertyName;
if (string.IsNullOrEmpty(propertyName)) {
Console.WriteLine ("Foreach registered handlers and invoke one by one");
} else {
Console.WriteLine ("Invoke handler for property {0}", propertyName);
}
return true;
}
return false;
}
}
public class ViewModel : ObservableObject {
private int mProp1;
private int mProp2;
public int Prop1 {
get { return mProp1; }
set {
mProp1 = value;
RaisePropertyChanged("Prop1");
}
}
public int Prop2 {
get { return mProp2; }
set {
mProp2 = value;
RaisePropertyChanged("Prop2");
}
}
public void RaiseAllPropertyChanged() {
RaisePropertyChanged(null);
}
}
And in a console app's Main we can call them like so:
var vm = new ViewModel();
var obs = new PropertyObserver();
// Normally this is done inside the PropertyObserver class.
PropertyChangedEventManager.AddListener(vm, obs, "Prop1");
PropertyChangedEventManager.AddListener(vm, obs, "Prop2");
vm.Prop1 = 1; // Results in a console line "Invoke handler for property Prop1"
vm.Prop2 = 2; // Results in a console line "Invoke handler for property Prop2"
// Results in two console lines: "Foreach registered handlers and invoke one by one", expected is only 1!
vm.RaiseAllPropertyChanged();
Okay, I didn't understand the AddListener() method before. I only need to register a listener once:
PropertyChangedEventManager.AddListener(vm, obs, string.Empty);
to listen to all PropertyChanged events of a source object. Doing this will produce the correct working of the PropertyObserver class:
vm.Prop1 = 1; // "Invoke handler for property Prop1"
vm.Prop2 = 2; // "Invoke handler for property Prop2"
// Now results in one console line "Foreach registered handlers and invoke one by one"
vm.RaisePropertyChanged();
Each registered listener with non-empty third argument (the property name) will respond to only the specified property name and null or string.Empty. So that's why the foreach was invoked twice on the original code.

How to destroy or detach a CollectionView

I observe an odd behaviour of WPF ItemsControls: If a set the ItemsSource to an object which implements INotifyCollectionChanged and after that set the ItemsSource to null, the CollectionView which was created to provide the data to the ItemsControl still listens to the CollectionChanged-event of the source object.
If now the source collection is changed through a different thread, the CollectionView throws an exception (without being attached to any control).
While I understand why this is happening, I’m really stuck resolving this situation.
Therefore the main question is, how can I destroy a CollectionView so that it does not listen any more to CollectionChanged-event. Or how can I disable it doing that / detaching the underlying collection.
Please note: The described behavior is not with ObservableCollection. The source object is an IEnumerable of T and implements INotifyCollectionChanged.
You're looking for the CollectionView.DetachFromSourceCollection() method:
var collectionView = CollectionViewSource.GetDefaultView(yourEnumerable) as CollectionView;
collectionView.DetachFromSourceCollection();
Update
It seems, that under .net 4.5 there is this desired functionality. See the answer of HighCore. For those not having 4.5 I leave my workaround here, maybe it helps someone:
class DetachableNotifyCollectionChangedWrapper : IEnumerable, INotifyCollectionChanged {
IEnumerable m_source;
public event NotifyCollectionChangedEventHandler CollectionChanged;
public DetachableNotifyCollectionChangedWrapper(IEnumerable enumerable) {
if (null == enumerable) throw new ArgumentNullException("enumerable"); ;
m_source = enumerable;
var ncc = m_source as INotifyCollectionChanged;
if (null != ncc) ncc.CollectionChanged += SourceCollectionChanged;
}
void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (null != CollectionChanged) CollectionChanged(this,e);
}
public IEnumerator GetEnumerator() {
return m_source.GetEnumerator();
}
public void Detach() {
var ncc = m_source as INotifyCollectionChanged;
if (null != ncc) ncc.CollectionChanged -= SourceCollectionChanged;
}
}
To use this, set the Wrapper as the ItemsSource of the ItemsControl. Before setting then the ItemsSource to null, call Detach on the wrapper to unregister the changed-event. Something as follows:
var wrapper = m_lstLog.ItemsSource as DetachableNotifyCollectionChangedWrapper;
if (null != wrapper) wrapper.Detach();
m_lstLog.ItemsSource = null;
The wrapper can also be used from within a ViewModel.

Implementing NotifyPropertyChanged without magic strings [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
typesafe NotifyPropertyChanged using linq expressions
I'm working on a large team application which is suffering from heavy use of magic strings in the form of NotifyPropertyChanged("PropertyName"), - the standard implementation when consulting Microsoft. We're also suffering from a great number of misnamed properties (working with an object model for a computation module that has hundreds of stored calculated properties) - all of which are bound to the UI.
My team experiences many bugs related to property name changes leading to incorrect magic strings and breaking bindings. I wish to solve the problem by implementing property changed notifications without using magic strings. The only solutions I've found for .Net 3.5 involve lambda expressions. (for example: Implementing INotifyPropertyChanged - does a better way exist?)
My manager is extremely worried about the performance cost of switching from
set { ... OnPropertyChanged("PropertyName"); }
to
set { ... OnPropertyChanged(() => PropertyName); }
where the name is extracted from
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null) throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
Consider an application like a spreadsheet where when a parameter changes, approximately a hundred values are recalculated and updated on the UI in real-time. Is making this change so expensive that it will impact the responsiveness of the UI? I can't even justify testing this change right now because it would take about 2 days worth of updating property setters in various projects and classes.
I did a thorough test of NotifyPropertyChanged to establish the impact of switching to the lambda expressions.
Here were my test results:
As you can see, using the lambda expression is roughly 5 times slower than the plain hard-coded string property change implementation, but users shouldn't fret, because even then it's capable of pumping out a hundred thousand property changes per second on my not so special work computer. As such, the benefit gained from no longer having to hard-code strings and being able to have one-line setters that take care of all your business far outweighs the performance cost to me.
Test 1 used the standard setter implementation, with a check to see that the property had actually changed:
public UInt64 TestValue1
{
get { return testValue1; }
set
{
if (value != testValue1)
{
testValue1 = value;
InvokePropertyChanged("TestValue1");
}
}
}
Test 2 was very similar, with the addition of a feature allowing the event to track the old value and the new value. Because this features was going to be implicit in my new base setter method, I wanted to see how much of the new overhead was due to that feature:
public UInt64 TestValue2
{
get { return testValue2; }
set
{
if (value != testValue2)
{
UInt64 temp = testValue2;
testValue2 = value;
InvokePropertyChanged("TestValue2", temp, testValue2);
}
}
}
Test 3 was where the rubber met the road, and I get to show off this new beautiful syntax for performing all observable property actions in one line:
public UInt64 TestValue3
{
get { return testValue3; }
set { SetNotifyingProperty(() => TestValue3, ref testValue3, value); }
}
Implementation
In my BindingObjectBase class, which all ViewModels end up inheriting, lies the implementation driving the new feature. I've stripped out the error handling so the meat of the function is clear:
protected void SetNotifyingProperty<T>(Expression<Func<T>> expression, ref T field, T value)
{
if (field == null || !field.Equals(value))
{
T oldValue = field;
field = value;
OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(GetPropertyName(expression), oldValue, value));
}
}
protected string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression memberExpression = (MemberExpression)expression.Body;
return memberExpression.Member.Name;
}
All three methods meet at the OnPropertyChanged routine, which is still the standard:
public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(sender, e);
}
Bonus
If anyone's curious, the PropertyChangedExtendedEventArgs is something I just came up with to extend the standard PropertyChangedEventArgs, so an instance of the extension can always be in place of the base. It leverages knowledge of the old value when a property is changed using SetNotifyingProperty, and makes this information available to the handler.
public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs
{
public virtual T OldValue { get; private set; }
public virtual T NewValue { get; private set; }
public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue)
: base(propertyName)
{
OldValue = oldValue;
NewValue = newValue;
}
}
Personally I like to use Microsoft PRISM's NotificationObject for this reason, and I would guess that their code is reasonably optimized since it's created by Microsoft.
It allows me to use code such as RaisePropertyChanged(() => this.Value);, in addition to keeping the "Magic Strings" so you don't break any existing code.
If I look at their code with Reflector, their implementation can be recreated with the code below
public class ViewModelBase : INotifyPropertyChanged
{
// Fields
private PropertyChangedEventHandler propertyChanged;
// Events
public event PropertyChangedEventHandler PropertyChanged
{
add
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
remove
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
}
protected void RaisePropertyChanged(params string[] propertyNames)
{
if (propertyNames == null)
{
throw new ArgumentNullException("propertyNames");
}
foreach (string str in propertyNames)
{
this.RaisePropertyChanged(str);
}
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
string propertyName = PropertySupport.ExtractPropertyName<T>(propertyExpression);
this.RaisePropertyChanged(propertyName);
}
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler propertyChanged = this.propertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public static class PropertySupport
{
// Methods
public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
MemberExpression body = propertyExpression.Body as MemberExpression;
if (body == null)
{
throw new ArgumentException("propertyExpression");
}
PropertyInfo member = body.Member as PropertyInfo;
if (member == null)
{
throw new ArgumentException("propertyExpression");
}
if (member.GetGetMethod(true).IsStatic)
{
throw new ArgumentException("propertyExpression");
}
return body.Member.Name;
}
}
If you're concerned that the lambda-expression-tree solution might be too slow, then profile it and find out. I suspect the time spent cracking open the expression tree would be quite a bit smaller than the amount of time the UI will spend refreshing in response.
If you find that it is too slow, and you need to use literal strings to meet your performance criteria, then here's one approach I've seen:
Create a base class that implements INotifyPropertyChanged, and give it a RaisePropertyChanged method. That method checks whether the event is null, creates the PropertyChangedEventArgs, and fires the event -- all the usual stuff.
But the method also contains some extra diagnostics -- it does some Reflection to make sure that the class really does have a property with that name. If the property doesn't exist, it throws an exception. If the property does exist, then it memoizes that result (e.g. by adding the property name to a static HashSet<string>), so it doesn't have to do the Reflection check again.
And there you go: your automated tests will start failing as soon as you rename a property but fail to update the magic string. (I'm assuming you have automated tests for your ViewModels, since that's the main reason to use MVVM.)
If you don't want to fail quite as noisily in production, you could put the extra diagnostic code inside #if DEBUG.
Actually we discussed this aswell for our projects and talked alot about the pros and cons. In the end, we decided to keep the regular method but used a field for it.
public class MyModel
{
public const string ValueProperty = "Value";
public int Value
{
get{return mValue;}
set{mValue = value; RaisePropertyChanged(ValueProperty);
}
}
This helps when refactoring, keeps our performance and is especially helpful when we use PropertyChangedEventManager, where we would need the hardcoded strings again.
public bool ReceiveWeakEvent(Type managerType, object sender, System.EventArgs e)
{
if(managerType == typeof(PropertyChangedEventManager))
{
var args = e as PropertyChangedEventArgs;
if(sender == model)
{
if (args.PropertyName == MyModel.ValueProperty)
{
}
return true;
}
}
}
One simple solution is to simply pre-process all files before compilation, detect the OnPropertyChanged calls that are defined in set { ... } blocks, determine the property name and fix the name parameter accordingly.
You could do this using an ad-hoc tool (that would be my recommendation), or use a real C# (or VB.NET) parser (like those which can be found here: Parser for C#).
I think it's reasonable way to do it. Of course, it's not very elegant nor smart, but it has zero runtime impact, and follows Microsoft rules.
If you want to save some compile time, you could have both ways using compilation directives, like this:
set
{
#if DEBUG // smart and fast compile way
OnPropertyChanged(() => PropertyName);
#else // dumb but efficient way
OnPropertyChanged("MyProp"); // this will be fixed by buid process
#endif
}

MainWindow.Closing event not always raised in Silverlight 4 OOB app

I've made a rather complex Silverlight 4 out-of-browser application. One of my main view models adds an event handler to the Application.Current.MainWindow.Closing event.
This works fine when the application is initially run. It is able to cancel the close operation.
However, sometimes after performing operations like showing and closing a ChildWindow, the MainWindow's Closing event is no longer calling my handler.
In the debugger, I added a watch to the MainWindow's underlying closing event delegate. It's not null before showing the ChildWindow. Then sometimes after the ChildWindow is closed the delegate is null. This is explains why my handler is not called any more. But why is this delegate getting nulled? And why is it only happening occasionally?
My application is not unbinding my event handler at any point.
This is the delegate I'm watching:
System.Windows.Application.Current.MainWindow.m_closingEvent
Other stuff: I'm using Caliburn Micro
I had the exact same problem. We have a large silverlight application running OOB.
For some reason the m_ClosingEvent was nulled after running for a while. I have not been able to find the cause of this issue but I think it may have something to do with us changing the root visual or all the child windows we show.
I´m using a class ApplicationWrapper.
public class ApplicationWrapper : IApplicationWrapper
{
public void Initialize()
{
HookCloseEvent(true);
}
private void HookCloseEvent(bool hook)
{
if (hook && IsRunningOutOfBrowser)
{
Application.Current.MainWindow.Closing += OnClosing;
}
else
{
if (IsRunningOutOfBrowser)
{
Application.Current.MainWindow.Closing -= OnClosing;
}
}
}
private void OnClosing(object sender, ClosingEventArgs e)
{
InvokeClosing(e);
}
... etc..
}
And the InvokeClosing method was never called. But when I changed it to
public class ApplicationWrapper : IApplicationWrapper
{
private Window _mainWindow;
public void Initialize()
{
if(IsRunningOutOfBrowser)
{
_mainWindow = Application.Current.MainWindow;
}
HookCloseEvent(true);
}
private void HookCloseEvent(bool hook)
{
if (hook && IsRunningOutOfBrowser)
{
_mainWindow.Closing += OnClosing;
}
else
{
if (IsRunningOutOfBrowser)
{
_mainWindow.Closing -= OnClosing;
}
}
}
private void OnClosing(object sender, ClosingEventArgs e)
{
InvokeClosing(e);
}
... etc...
}
The m_ClosingEvent isn´t nulled.
So, try to just store the "initial" MainWindow in a field and check if that solves your problem.
Instead of hooking to the event, why not register a service instead? Create a class that implements IApplicationService and IApplicationLifetimeAware. The latter gives you an "onexiting" and "onexited" pair of events. You place the service in the application by pointing to it in a section called in your App.xaml. I've used this for many projects and never had an issue with the exiting methods not being called.
Ok, after pulling out my hair and many false starts I finally found the answer - it seems to be a known bug with the Closing event, OOB and ChildWindows open/closes...
The trick is to store a static reference to the Main Window:
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
//you have to store this to work around the bug
//http://forums.silverlight.net/forums/p/185664/424174.aspx
_mainWindow = App.GetApp.MainWindow;
App.GetApp.MainWindow.Closing += (s, e1) =>
{
if (UIUtilities.ShowMessage("Would you like to exit AMT Mobile?", "Exit Application", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
{
e1.Cancel = true;
}
};
}

How to run batched WCF service calls in Silverlight BackgroundWorker

Is there any existing plumbing to run WCF calls in batches in a BackgroundWorker?
Obviously since all Silverlight WCF calls are async - if I run them all in a backgroundworker they will all return instantly.
I just don't want to implement a nasty hack if theres a nice way to run service calls and collect the results.
Doesnt matter what order they are done in
All operations are independent
I'd like to have no more than 5 items running at once
Edit: i've also noticed (when using Fiddler) that no more than about 7 calls are able to be sent at any one time. Even when running out-of-browser this limit applies. Is this due to my default browser settings - or configurable also. obviously its a poor man's solution (and not suitable for what i want) but something I'll probably need to take account of to make sure the rest of my app remains responsive if i'm running this as a background task and don't want it using up all my connections.
I think your best bet would be to have your main thread put service request items into a Queue that is shared with a BackgroundWorker thread. The BackgroundWorker can then read from the Queue, and when it detects a new item, initiate the async WCF service request, and setup to handle the AsyncCompletion event. Don't forget to lock the Queue before you call Enqueue() or Dequeue() from different threads.
Here is some code that suggests the beginning of a solution:
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace MyApplication
{
public class RequestItem
{
public string RequestItemData { get; set; }
}
public class ServiceHelper
{
private BackgroundWorker _Worker = new BackgroundWorker();
private Queue<RequestItem> _Queue = new Queue<RequestItem>();
private List<RequestItem> _ActiveRequests = new List<RequestItem>();
private const int _MaxRequests = 3;
public ServiceHelper()
{
_Worker.DoWork += DoWork;
_Worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
while (!_Worker.CancellationPending)
{
// TBD: Add a N millisecond timer here
// so we are not constantly checking the Queue
// Don't bother checking the queue
// if we already have MaxRequests in process
int _NumRequests = 0;
lock (_ActiveRequests)
{
_NumRequests = _ActiveRequests.Count;
}
if (_NumRequests >= _MaxRequests)
continue;
// Check the queue for new request items
RequestItem item = null;
lock (_Queue)
{
RequestItem item = _Queue.Dequeue();
}
if (item == null)
continue;
// We found a new request item!
lock (_ActiveRequests)
{
_ActiveRequests.Add(item);
}
// TBD: Initiate an async service request,
// something like the following:
try
{
MyServiceRequestClient proxy = new MyServiceRequestClient();
proxy.RequestCompleted += OnRequestCompleted;
proxy.RequestAsync(item);
}
catch (Exception ex)
{
}
}
}
private void OnRequestCompleted(object sender, RequestCompletedEventArgs e)
{
try
{
if (e.Error != null || e.Cancelled)
return;
RequestItem item = e.Result;
lock (_ActiveRequests)
{
_ActiveRequests.Remove(item);
}
}
catch (Exception ex)
{
}
}
public void AddRequest(RequestItem item)
{
lock (_Queue)
{
_Queue.Enqueue(item);
}
}
}
}
Let me know if I can offer more help.

Resources