In what cases I really have a necessity to use an IObservable<>.SubscribeOnDispatcher method in Silverlight/WPF applications? I.e. I'm asking for particular cases, when this call is a must.
Thanks in advance
Its a must when these conditions are true:
Your Observable is based on something that generates callbacks/events that are not already guaranteed to be be on the main UI thread (eg. HttpWebRequest)
The code that responds to the arrival these items needs to manipulate UI elements
Other code in the chain must not execute until the previous manipulations of UI elements are complete.
If 1 isn't true then things arrive from it on the UI thread already. If 2 isn't true then there being on the UI thread isn't important. If 3 isn't true then code at stage 2 could BeginInvoke some of its UI work on the Dispatcher itself.
Related
I am supposed to work on a wpf legacy application( and desktop app is a new beast for me).
I have read that consumming task should not be launched on the ui thread : but I find this following code in the code behind of a view :
bool isSearching = true;
try
{
Task<ProductSearchResult>.Factory
.StartNew(() => DBCatalogService.Search( search.Criteria, search.CriteriaPage, search.CriteriaResultByPage)
.ContinueWith(res => LoadResult(res, search.Criteria, search.CriteriaPage, search.CriteriaResultByPage),
TaskScheduler.FromCurrentSynchronizationContext())
.ContinueWith(s => isSearching = false);
}
catch
{
...
}
I am wondering it will not cause any trouble.
I know that it's sounds weird to call the database directly from the view code behind, but I just want to know if it could freeze the ui thread or something like this.
Thank you for your advice on this matter.
My question is : does the sample code that I provided would block the UI thread and have to be considered harmfull or not ?
The call to the DBCatalogService.Search method will not block the UI thread since it is being invoked on a background thread using the task parallel library (TPL).
The call to the LoadResult method will however be executed on the UI thread once the task that calls the Search method has completed.
This is fine though since this method probably sets some properties of some UI elements based on the result of the search and you must do this on the UI thread. This is because WPF controls have thread affinity, meaning that a control can only be accessed on the thread on which it was originally created.
So no, the sample code you have provided should not be considered "harmfull" in terms of UI responsiveness assuming that the LoadResult doesn't perform any strange and potentially long-running operations.
If you block the UI thread (dispatcher thread) with a long-running operation such as a synchronous DB request, your application will be unresponsive until the thread is unblocked.
You can avoid this by either:
Doing the blocking/synchronous operation on another thread
Making the operation non-blocking/asynchronous
Both of the above
Using async/await can make your code read much like the synchronous form, but with asynchronous behaviour. It should be much clearer than the code sample you give in the question. However you need an async form of your search.
If you do use another thread, remember to dispatch back onto the UI thread if you have to update UI properties.
I have an WPF application which contains many classes that support INotifyProprtyChange interface. The property on this classes are changed at high rate from different threads and the problem is that in some cases application UI thread hangs , along with the UI thread other threads that have code calling PropertyChange also hangs while trying update properties.
I did a deadlock check with Windbg but it could detect none.
Now i looked at the stack trace of the threads holding locks and what i always see is that at least one same or different thread has
00000000002d0ab8 000000007712908a [HelperMethodFrame_1OBJ: 00000000002d0ab8] System.Threading.SynchronizationContext.WaitHelper(IntPtr[], Boolean, Int32)
00000000002d13b0 000000007712908a [GCFrame: 00000000002d13b0]
00000000002d16c8 000000007712908a [HelperMethodFrame_1OBJ: 00000000002d16c8] System.Threading.ReaderWriterLock.AcquireReaderLockInternal(Int32)
00000000002d17f0 000007fef1bcf1a0 MS.Internal.ReaderWriterLockWrapper.get_ReadLock()
00000000002d1830 000007fef1ba8d44 System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(System.Object, System.ComponentModel.PropertyChangedEventArgs)
and another
000000001f64d138 000000007738186a [HelperMethodFrame_1OBJ: 000000001f64d138] System.Threading.ReaderWriterLock.AcquireReaderLockInternal(Int32)
000000001f64d260 000007fef1bcf1a0 MS.Internal.ReaderWriterLockWrapper.get_ReadLock()
000000001f64d2a0 000007fef1ba8d44 System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(System.Object, System.ComponentModel.PropertyChangedEventArgs)
So its looks like PropertyChangedEventManager wait for some thread to complete while other threads wait to acquire lock?
Now i am having troubles figuring out why this occurs as its sporadic and usually happens when there is many property change events. From what i see other threads in application that not calling property change continue to run normally.
As far as I know PropertyNotifyChanged is only supported in the UI thread.
Just guessing. In bigger environments one problem happends quiet easy: 2 properties update each other endlessly. The setter of prop A calls the setter of prop B which in turn calls the setter of A again. Usually of course not that obvious as described but could be worth to look at.
Is it possible, or more precisely how is it possible to use RX.Net to listen to a number and different variety of (WinForms) controls' .TextChanged/.RowsChanged/.SelectionChanged events and whenever one condition is fullfilled (ControlA.Text isn't empty, ControlB.RowsCount > 0 etc) enable that one DoSomething button.
I am asking because currently we have a lengthy if/then statement in each of these events' handlers and maintaining them if the condition changes is, due to duplicate code, quite error prone and that's why, if possible, I think it would be nice to take the stream of events and put the condition in one place.
Has anyone done that?
You can use Observable.FromEventPattern in combination with Join patterns, with Observable.When, Observable.And and Observable.Then, to create observables which will fire depending on various conditions, like combinations of events. For example, consider my answer here: Reactive Extensions for .NET (Rx): Take action once all events are completed
You should be able to use .FromEventPattern() to create observables for each of those events and then use CombineLatest() to do your logic on the current overall state and determine whether your button should be enabled, in one place.
Acording to my understanding Dispatcher.Invoke and Dispatcher.BeginInvoke executes on UI thread, The only difference is That Invoke is synchronous and BeginInvoke is asynchronous.My problem is when i use this code
EDisc.App.Current.Dispatcher.
Invoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));
Value of context is returned. However with the below code
EDisc.App.Current.Dispatcher.
BeginInvoke(
DispatcherPriority.Normal, new Action(delegate
{
context = NavigationManager.CurrentPage.DataContext;
}));
Context is null and i get an InvalidOperation Exception saying "
The calling thread cannot access this object because a different thread owns it.I am calling this from a WCF service which is executing with UseSynchronizationContext = false .Can anybody explain this behaviour?
Both BeginInvoke and Invoke will end up calling an internal method called BeginInvokeImpl to do the work. The difference is that Invoke then waits for the operation to complete before returning.
And there's one other difference: if you are already on the UI thread and you're using DispatcherPriority.Send Invoke will actually invoke the method directly without going via BeginInvokeImpl, meaning that the operation is processed without going via the message queue. (If you're not using Send then any other messages already queued up with higher property than your operation will get processed first.)
But since you're presumably not on the UI thread here - you're on some WCF callback - that special case won't apply. So Invoke ends up calling into the same underlying implementation as BeginInvoke.
From the information you've provided, I'd have to guess that there's a missing detail somewhere here. The code you've shown should work fine, unless perhaps you have multiple UI threads in your application, and the page that happens to be in CurrentPage belongs to different threads from time to time.
If you do have multiple UI threads, then the approach you're using - pushing everything through the current Application object's dispatcher - isn't going to work, because you'll have multiple dispatchers. You'd need to get the right dispatcher for whichever UI element you're planning to touch.
Incidentally, one way you might accidentally end up with multiple UI threads is if you construct a UI object (e.g. a Page) on some worker thread or callback. Is it possible that you've done that somewhere?
Im tring to start unit testing with silverlight and some of the samples online use the following statements
EnqueueCallback
EnqueueConditional
EnqueueTestComplete
where do these live?
Ok found my answer. If your test inherits from WorkItemTest (or PresentationTest, or SilverlightTest), you’ll be able to call from your tests:
TestComplete()
Instructs the framework that your test method is finished, and to move onto the next result. This can be added to event callbacks, delegates, etc. You should not do any more work or your test after calling this.
EnqueueTestComplete
Enqueues an action to call TestComplete. This is the most-used way of calling TestComplete when a set of work is done, and would typically be the last Enqueue* method call.
EnqueueCallback
Enqueues an Action (delegate, simple lambda, etc.). The work item effectively calls the Action, then moves on. Alternatively, this enqueue method also takes an array of Actions, allowing you to chain many Action calls together in order.
EnqueueConditional
Takes a Func conditional statement / predicate. Each time the work item is evaluated, the function is called. When it returns True, the work item is complete and execution will continue. After each invoke of the predicate, the test framework will unwind the stack, allowing other work to happen, before coming back to try the condition again.
EnqueueDelay
This method will enqueue a work item that takes either a TimeSpan object or an integer representing the number of milliseconds at minimum to delay before continuing. This is not an exact timer, but rather, a way to ensure that at least a minimum amount of time continues. It is more like a DoEvents call than it is like a Sleep call, since it will not block the UI thread.