Cross Thread Exception with Throttle in Reactive Extensions - silverlight

I am using Reactive Extensions to verification of a textbox input.
I am trying to use the .Throttle(TimeSpan.FromMilliseconds(500)).
But when I add the .Throttle() method a cross thread exception is thrown when accessing a UI object in the .Subscribe() method.
It works 100% without the Throttle, why is it breaking?
My code:
var textChangedEvent = Observable.FromEvent<TextChangedEventArgs>(usernameTextbox, "TextChanged")
.Throttle(TimeSpan.FromMilliseconds(500))
textChangedEvent.Subscribe(changed =>
{
TextBox oUsernameTextBox = changed.Sender as TextBox;
//Accessing oUsernameTextBox throws Cross Thread Exception
});
Thanks
-Oliver

By default Throttle uses the ThreadpoolScheduler so events will not arrive on the UI Thread. Since you need the events on the UI thread use:-
var textChangedEvent = Observable.FromEvent<TextChangedEventArgs>(usernameTextbox, "TextChanged")
.Throttle(TimeSpan.FromMilliseconds(500), Scheduler.Dispatcher);
This will put the events back on the UI Thread.

I had to tweak the code a bit to make it work in a LightSwitch (SilverLight 4) application with Rx v1.0.10621 due to some interface changes in Rx since when this question had been asked.
Need to install Rx and to reference System.Reactive and System.Reactive.Windows.Threading assemblies (for LightSwitch this reference go in the Client project).
Then use this code to throttle a the TextChange event on the text box:
(Note: For lightswitch this code goes in the ControlAvailable handler)
var textChangedEvent = Observable
.FromEventPattern<TextChangedEventArgs>(e.Control, "TextChanged")
.Throttle(TimeSpan.FromMilliseconds(500))
.ObserveOnDispatcher();
textChangedEvent.Subscribe(changed =>
{
var tb = changed.Sender as TextBox;
if (tb.Text.Length >= 3) // don't search for keywords shorter than 3 chars
{
// search
}
});

Related

Rx reactive extensions Observeondispatcher unit test error: The current thread has no Dispatcher associated with it

I want to unit test a view model which contains a registration like:
public SampleViewModel(IUnityContainer container)
{
...
Observable.FromEventPattern<PropertyChangedEventArgs>(gridViewModel, "PropertyChanged")
.**ObserveOnDispatcher()**
.Subscribe(_ => this.Update());
...
}
When I run the unit test it tells me that "The current thread has no Dispatcher associated with it." when reaching this code.
One solution would be to use a Scheduler but I don't want to modify the Viewmodel.
Is there a solution to make the unit test pass this statement without getting an error?
I would suggest that you provide you own IScheduler implementation to ObserveOn(IScheduler) instead of using the ObserveOnDispatcher() operator. I have used techniques for loading a DispatcherFrame or a Dispatcher but the problem is that you are still using a Dispatcher. Eventually I found that you just "fall off the cliff" especially once you have long running background threads involved. Following the guidelines of "No threading in Unit tests" just dont let the dispatcher get near your ViewModels! Your Unit tests will run much, much faster.
A far superior way to deal with this is to inject an interface that gives access to your Dispatcher Scheduler (via the IScheduler interface). This allows you to substitute in an implementation that exposes the TestScheduler. You now can control time in your unit test. You can control and validate which actions are marshalled to each scheduler.
This is a really old (pre-Rx) post on 'Unit' testing WPF with Dispatcher calls from early 2009. It seemed like a good idea at the time.
https://leecampbell.com/2009/02/17/responsive-wpf-user-interfaces-part-5/
More information on Testing with Rx and the TestScheduler is found in my other site on Rx
http://introtorx.com/Content/v1.0.10621.0/16_TestingRx.html
This works for me.
When setting up the unit test I create an application to simulate the environment for my VM:
static Application App;
static void BeforeTestRun()
{
var waitForApplicationRun = new ManualResetEventSlim();
Task.Run(() =>
{
App = new Application();
App.Startup += (s, e) => { waitForApplicationRun.Set(); };
App.Run();
});
waitForApplicationRun.Wait();
}
and this is how I use it to instanciate the view model.
App.Dispatcher.Invoke(() => { this.viewModel = new ViewModel(); });
To properly unit test your viewmodel, you really need to be able to supply all of its dependencies. In this case, your viewmodel has a dependency upon the dispatcher. Making your viewmodel take a IScheduler dependency is the ideal way. But if you really don't want to do that, then try looking at this duplicate question: Unit test IObservable<T> with ObserveOnDispatcher
I found a solution for avoiding the error, simply from Unit Test code instantiate the ViewModel by using a dispatcher like:
SampleViewModel sampleViewModel;
var dispatcher = Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher;
dispatcher.Invoke((Action)(() => sampleViewModel = new SampleViewModel(this.container);
That's all and seems to work without modifying current code, maybe there are also better solutions.

Replacing methods that use backgroundworker to async / tpl (.NET 4.0)

My questions are many. Since I saw. NET 4.5, I was very impressed. Unfortunately all my projects are .NET 4.0 and I am not thinking about migrating. So I would like to simplify my code.
Currently, most of my code that usually take enough time to freeze the screen, I do the following:
BackgroundWorker bd = new BackgroundWorker();
bd.DoWork += (a, r) =>
{
r.Result = ProcessMethod(r.Argument);
};
bd.RunWorkerCompleted += (a, r) =>
{
UpdateView(r.Result);
};
bd.RunWorkerAsync(args);
Honestly, I'm tired of it. And that becomes a big problem when there is a logic complex user interaction.
I wonder, how to simplify this logic? (Remember that I'm with. Net 4.0) I noticed a few things by google, but not found anything easy to implement and suitable for my needs.
I thought this solution below:
var foo = args as Foo;
var result = AsyncHelper.CustomInvoke<Foo>(ProcessMethod, foo);
UpdateView(result);
public static class AsyncHelper
{
public static T CustomInvoke<T>(Func<T, T> func, T param) where T : class
{
T result = null;
DispatcherFrame frame = new DispatcherFrame();
Task.Factory.StartNew(() =>
{
result = func(param);
frame.Continue = false;
});
Dispatcher.PushFrame(frame);
return result;
}
}
I am not sure about the impact is on manipulating the dispatcher frame.
But I know That it would work very well, for example, I could use it in all the events of controls without bothering to freeze the screen.
My knowledge about generic types, covariance, contravariance is limited, maybe this code can be improved.
I thought of other things using Task.Factory.StartNew and Dispatcher.Invoke, but nothing that seems interesting and simple to use. Can anyone give me some light?
You should just use the Task Parallel Library (TPL). The key is specifying the TaskScheduler for the current SynchronizationContext for any continuations in which you update the UI. For example:
Task.Factory.StartNew(() =>
{
return ProcessMethod(yourArgument);
})
.ContinueWith(antecedent =>
{
UpdateView(antecedent.Result);
},
TaskScheduler.FromCurrentSynchronizationContext());
Aside from some exception handling when accessing the antecedent's Result property, that's all there is too it. By using FromCurrentSynchronizationContext() the ambient SynchronizationContext that comes from WPF (i.e. the DispatcherSynchronizationContext) will be used to execute the continuation. This is the same as calling Dispatcher.[Begin]Invoke, but you are completely abstracted from it.
If you wanted to get even "cleaner", if you control ProcessMethod I would actually rewrite that to return a Task and let it own how that gets spun up (can still use StartNew internally). That way you abstract the caller from the async execution decisions that ProcessMethod might want to make on its own and instead they only have to worry about chaining on a continuation to wait for the result.
UPDATE 5/22/2013
It should be noted that with the advent of .NET 4.5 and the async language support in C# this prescribed technique is outdated and you can simply rely on those features to execute a specific task using await Task.Run and then execution after that will take place on the Dispatcher thread again automagically. So something like this:
MyResultType processingResult = await Task.Run(() =>
{
return ProcessMethod(yourArgument);
});
UpdateView(processingResult);
How about encapsulating the code that is always the same in a reusable component? You could create a Freezable which implements ICommand, exposes a property of Type DoWorkEventHandler and a Result property. On ICommand.Executed, it would create a BackgroundWorker and wire up the delegates for DoWork and Completed, using the value of the DoWorkEventHandler as event handler, and handling Completed in a way that it sets its own Result property to the result returned in the event.
You'd configure the component in XAML, using a converter to bind the DoWorkEventHandler property to a method on the ViewModel (I assume you've got one), and bind your View to the component's Result property, so it gets updated automatically when Result does a change notification.
The advantages of this solution are: it is reusable, and it works with XAML only, so no more glue code in your ViewModel just for handling BackgroundWorkers. If you don't need your background process to report progress, it could even be unaware that it runs on a background thread, so you can decide in the XAML whether you want to call a method synchronously or asynchronously.
A few months have passed, but could this help you?
Using async/await without .NET Framework 4.5

Getting Progress Updates using HttpWebRequest and TPL (Tasks)

I would like to track the progress of a download taking place on a separate thread. I know that System.Net.WebClient has a DownloadStringAsync method, but it doesn't work directly with the new TPL types (TaskFactory, Task, etc.).
Can progress be tracked using the HttpRequest and HttpResponse classes?
What's the best class for tracking progress? The less overhead the better.
Are there times when the size of the response is unknown, aka, progress can't be tracked?
What's the best way to synchronize with the UI thread whenever progress is made?
Most examples show Tasks updating the UI only after the entire task is complete. These examples use continuations taking a UI synchronization context that avoids needing to work with a Dispatcher directly.
The idea is to show a grid view (in WPF) with all the downloads with progress bars. I am going to adding new rows and updating progress bars all the time. I'm trying to avoid turning this code into a mess.
DownloadStringAsync and the other event methods work very well with TPL in .NET 4.0 (check for EAP and TPL). In general, TPL does support event async programming through the TaskCompletionSource. The Begin/EndXXX model (APM) is supported through the Task.FromAsync method. You can find a detailed description TPL and Traditional .NET Asynchronous Programming.
The ParallelExtensionExtras library has a set of WebClient extensions methods like DownloadStringTask that return a task which completes when the appropriate event is fired.
The following code will create a Task that will complete when download finishes:
public Task<string> DownloadStringTask(WebClient client,Uri uri)
{
var tcs = new TaskCompletionSource<string>();
client.DownloadStringCompleted += (o, a) => tcs.SetResult(a.Result);
client.DownloadStringAsync(uri);
return tcs.Task;
}
As for updating the UI, you can easily use the DownloadProgressChanged event to provide feedback,eg:
using (var client = new WebClient())
{
client.DownloadProgressChanged += (o, a) => Console.WriteLine("{0}",a.ProgressPercentage);
var task = DownloadStringTask(client,new Uri("http://www.stackoverflow.com"));
var write=task.ContinueWith(t => Console.WriteLine("Got {0} chars", t.Result.Length));
write.Wait();
Console.ReadKey();
}
If you use data binding to provide the progress values to your progress bars, you can just update the progress value properties. If you update the progress bars directly (not a good idea), you will have to marshal the call to the UI thread using the progress bar's dispatcher, eg. like this
void UpdateProgress(int percent)
{
if (progressBar1.CheckAccess())
progressBar1.Value = percent;
else
{
progressBar1.Dispatcher.Invoke(new Action(()=>UpdateProgress(percent)));
}
}
....
client.DownloadProgressChanged += (o, a) => UpdateProgress(a.ProgressPercentage);

Force redraw before long running operations

When you have a button, and do something like:
Private Function Button_OnClick
Button.Enabled = False
[LONG OPERATION]
End Function
Then the button will not be grayed, because the long operation prevents the UI thread from repainting the control. I know the right design is to start a background thread / dispatcher, but sometimes that's too much hassle for a simple operation.
So how do I force the button to redraw in disabled state? I tried .UpdateLayout() on the Button, but it didn't have any effects. I also tried System.Windows.Forms.DoEvents() which normally works when using WinForms, but it also had no effect.
The following code will do what you're looking for. However I would not use it. Use the BackgroundWorker class for long time operations. It's easy to use and very stable.
Here the code:
public static void ProcessUITasks() {
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(object parameter) {
frame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(frame);
}
Here you will find a sample on how to use the BackgroundWorker.
InvalidateVisual(); #HCL is right... don't do this
Like you say, it is better to start use a background thread / dispatcher and keep the UI thread unblocked. Consider looking at the Reactive Extensions library from Microsoft for high level asynchronous ui programming
In Windows.Forms, you can Button.Refresh().
In Windows.Forms or WPF, you can yield to the message pump to let it redraw. Async/Await were designed to allow you to do this without the nastiness of HCL's answer.
Private Async Function Button_OnClick
Button.Enabled = False
Await Task.Yield
[LONG OPERATION]
End Function

Exception while using ExecuteQuery() in Silverlight client object model

I have been developing a Silverlight user control for SharePoint using the Client Object model. Here is the coding
InitializeComponent();
ctx = ClientContext.Current;
Web web = ctx.Web;
ctx.Load(web, oweb => oweb.Title);
ctx.Load(web, oweb => oweb.Lists);
ctx.ExecuteQuery();
I heard tht SIlverlight supports both ExecuteQuery() and ExecuteQueryAsync() methods. But I'm getting an Exception message like this "he method or property that is called may block the UI thread and it is not allowed. Please use background thread to invoke the method or property, for example, using System.Threading.ThreadPool.QueueUserWorkItem method to invoke the method or property."
Can anyone tell me where am I going wrong and how to use ExecuteQuery() method ?? Thank you.
I might be off base here, but as I understand it, ExecuteQuery() requires you to create a thread so you aren't calling a stop to the UI thread when you invoke the method. The reason you use ExecuteQueryAsync is exactly that: ExecuteQueryAsync performs the operation on a seperate thread, then you just call back in to the UI thread using the dispather:
ctx.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
...
private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgs args)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
doStuff();
}));
}

Resources