Here are the 2 ways we are using trying to use thread/dispatcher for multi tasking a few things:
I am wondering if anyone has any suggestions which one is better option.
Snippet 1:
Thread t = new Thread(new ThreadStart(delegate
{
MyMethod();
}));
t.IsBackground = true;
t.Start();
t.Join();
Snippet 2:
Dispatcher.CurrentDispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(dummyDelegate)delegate
{
MyMethod();
}
);
Please advise.
Thanks
N
Neither is "better": they are different.
The first example runs MyMethod on a background thread. So if MyMethod blocks, for example on network activity or doing something computation intensive, this doesn't block the UI thread, and the UI remains responsive. (Though since your sample code blocks and waits, you are currently losing this advantage anyway.) The downside is that MyMethod has to jump through some minor hoops if it wants to read or update the UI.
The second example runs MyMethod on the UI thread. This allows MyMethod to interact without restriction with elements in the UI, but is unsuitable if MyMethod takes a long time because it freezes the UI while MyMethod is running.
So it depends on what MyMethod does. If MyMethod updates a couple of UI elements and then exits, use the second option. If MyMethod loads files or downloads data, and/or performs lengthy computation, use the first.
There is also a third option: use the Threadpool to execute a short-lived asynchronous call. For example:
System.Threading.Threadpool.QueueUserWorkItem(
delegate(object context)
{
// context is unused
MyMethod();
});
This will use a thread from the threadpool to execute MyMethod. When the method completes, the thread will be returned to the pool. The advantage of this method is that you don't have to manage the lifetime of the threads yourself, and you don't incure the memory and performance overhead of creating and destroying the thread.
Anything wrong with using good ole BackgroundWorker?
It's not WinForms specific so you can still use it in WPF.
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 want to render a chart with the DevExpress ChartControl via the WiForm DrawToBitmap() function on a separate thread.
I try something like:
Form yourForm;
Thread thread = new Thread( () =>
{
yourForm = new HiddenForm();
Application.Run(yourForm);
});
thread.ApartmentState = ApartmentState.STA;
thread.Start();
yourForm.Invoke(chartRenderingFunction)
And simple make sure the Hidden never actually gets displayed. However, I don't need that hidden form, and there is a parameterless form of Application.Run(). However, if I run that, it doesn't return. So my question is once I call Application.Run() inside a thread, how do I inject code in it?
Well, you actually really do need that hidden window. The only way to get code to run on that thread. Somebody must call PostMessage() and that requires a window handle. Your Invoke() call makes that call. You really should use BeginInvoke() instead, there's no point in starting a thread if you are going to wait for the call to complete.
Using Application.Run(yourForm) is going to make the window visible. You can stop it from becoming visible by overriding the SetVisibleCore() method in your HiddenForm class:
protected override void SetVisibleCore(bool value) {
if (!this.IsHandleCreated) {
CreateHandle();
value = false;
ThreadReady.Set();
}
base.SetVisibleCore(value);
}
The CreateHandle() call is necessary to make sure that the window is created so it can process the PostMessage() notifications. Also note the added AutoResetEvent (ThreadReady), you are going to have to call ThreadReady.WaitOne() after calling the thread's Start() method to ensure that your BeginInvoke() call is going to work. Dispose the form to get the thread to exit or call Application.Exit().
Last but not least, be very careful with using non-trivial controls on that thread. A chart control certainly is not indicated. You'll have long-lasting problems if that control uses the SystemEvents class for example. Your worker thread will get it to raise events on that worker thread. But it won't be around anymore after the chart is printed. You'll now get the events fired on an arbitrary threadpool thread, very nasty. A deadlock is a common mishap, particularly apt to trigger when locking the workstation.
I wonder whether it is possible to understand which code pieces are executed on UI from source code just depending on static analysis in Windows Phone development.
I try to implement a static analysis finding places in which Dispatcher.(Begin)Invoke is used unnecessarily.
These are the places that UI thread definitely executes:
event handlers which gets "RoutedEventArgs" as a parameter
Constructors of UI elements
the definitions of method calls in above methods (means that transitively looking at call graphs of these event handler methods and UI constructors)
Is there any other place or is there something wrong about above list?
Every method called by using the Dispatcher or the right SynchronizationContext will execute on the UI thread. That makes exhaustive static analysis impossible. For instance, the callback of the WebClient class executes on the UI thread. How are you supposed to predict those corner cases?
A quick tip though, quite useful is you have a method that can be called both from a UI or a non-UI thread. By calling the method Dispatcher.CheckAccess() (this method isn't shown by the intellisense in Visual Studio, so it's hard to discover), you can know if you need to call the Dispatcher or not:
if (Dispatcher.CheckAccess())
{
// In the UI thread
SomeMethod();
}
else
{
// Not in the UI thread
Dispatcher.BeginInvoke(SomeMethod);
}
From there, you can write a wrapper:
public void CallDispatcherIfNeeded(Action method) // You might want a shorter name
{
if (Dispatcher.CheckAccess())
{
// In the UI thread
method();
}
else
{
// Not in the UI thread
Dispatcher.BeginInvoke(method);
}
}
And then you just have to call it, without worrying whether you're on the UI thread or not:
CallDispatcherIfNeeded(SomeMethod);
That said, if your code is correctly written, it's quite rare to need this kind of trick.
I would look at when Dispatcher.BeginInvoke is actually needed, not the other way around.
It is almost never needed, excepted when handing an async completed event which may start out on a background thread, and thus if you want to do something with the UI, you need to marshal it over to the UI thread.
In other words, unless you need to do something with the UI from a background thread, you don't need it.
Greg
Dart has many ways of creating, processing and returning async functions. One of the most common methods is to:
import 'dart:async';
var completer = new Completer();
// Previously this would have been new Timer(0, () => ....);
Timer.run(() => completer.complete(doSomethingHere()));
return completer.future;
However dart also provides a constructor for Future's directly such as:
import 'dart:async';
return new Future.of(() => doSomethingHere());
I am aware that the Timer.run() version may be cancelled using the return value of the static method. And that the new Future.of() version is slightly less code, is there a particular benefit to using new Future.of() over Timer.run() (or vice versa). Or are the benefits simply those that I just mentioned?
Future.of returns a Future, Timer.run does not return anything. To me, this is the main difference.
I use Future.of if I want to return a value as a Future.
I use Timer.run if I want to run some function later, and I don't care about the value that it produces.
One big difference is when the function is run, though.
For Future.of, the function is run in the current event loop, and only its value is made available in the next event loop.
For Timer.run, the function is run in the next event loop.
Don't forget that they are two different things. Timer can be used anywhere for so many purposes. It could be used on the client-side for waiting for layout to happen before running more code, for example. So, it may not have anything to do with futures. I use the timer sometimes in client-side code to wait for a layout.
Timer is a generic class for delaying the running of some code. No matter whether it has anything to do with futures or not. Another example could be client-side animations. Nothing to do with futures or dealing with data asynchronously.
Futures, however, are monads that help you to program asynchronous programs. Basically a replacement to passing plain callback functions.
Use new Future.of() when writing asynchronous programs and it suits your situation (the same goes with new Future.immediate().
Use the Timer class if you want to delay the running of some code.
If what you want to do is to use futures for asynchronous programming and at the same time delay the code, forget the timer class unless you need some real delay (more than 0/next event).
What solutions do I have if I want to prevent the UI from freezing while I deserialize a large number of UI elements in WPF? I'm getting errors complainig that the objects belong on the UI Thread when I'm trying to load them in another thread. So, what options do I have to prevent the Vista "Program not responding" error while I'm loading my UI data? Can I rely on a single-threaded solution, or am I missing something regarding perhaps multiple UI Threads?
If you only use a single thread then the UI will freeze while you do any amount of processing.
If you use a BackgroundWorker thread you'll have more control over what happens & when.
To update the UI you need to use Dispatcher.Invoke from your background thread to marshal the call across the thread boundary.
Dispatcher.Invoke(DispatcherPriority.Background,
new Action(() => this.TextBlock.Text = "Processing");
You can turn the flow of control on its head using DispatcherFrames, allowing a deserialization to proceed on the UI thread in the background.
First you need a way to get control periodically during deserialization. No matter what deserializer you are using, it will have to call property sets on your objects, so you can usually add code to the property setters. Alternatively you could modify the deserializer. In any case, make sure your code is called frequently enough
Each time you receive control, all you need to do is:
Create a DispatcherFrame
Queue an event to the dispatcher using BeginInvoke that sets Continue=false on the frame
Use PushFrame to start the frame running on the Dispatcher
In addition, when calling the deserializer itself make sure you do it from Dispatcher.BeginInvoke, or that your calling code doesn't hold any locks etc.
Here's how it would look:
public partial class MyWindow
{
SomeDeserializer _deserializer = new SomeDeserializer();
byte[] _sourceData;
object _deserializedObject;
...
void LoadButton_Click(...)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
_deserializedObject = _deserializer.DeserializeObject(_sourceData);
}));
}
}
public class OneOfTheObjectsBeingDeserializedFrequently
{
...
public string SomePropertyThatIsFrequentlySet
{
get { ... }
set { ...; BackgroundThreadingSolution.DoEvents(); }
}
}
public class BackgroundThreadingSolution
{
[ThreadLocal]
static DateTime _nextDispatchTime;
public static void DoEvents()
{
// Limit dispatcher queue running to once every 200ms
var now = DateTime.Now;
if(now < _nextDispatchTime) return;
_nextDispatchTime = now.AddMilliseconds(200);
// Run the dispatcher for everything over background priority
var frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
frame.Continue = false;
}));
Dispatcher.PushFrame(frame);
}
}
Checking DateTime.Now in DoEvents() isn't actually required for this technique to work, but will improve performance if SomeProperty is set very frequently during deserialization.
Edit: Right after I wrote this I realized there is an easier way to implement the DoEvents method. Instead of using DispatcherFrame, simply use Dispatcher.Invoke with an empty action:
public static void DoEvents()
{
// Limit dispatcher queue running to once every 200ms
var now = DateTime.Now;
if(now < _nextDispatchTime) return;
_nextDispatchTime = now.AddMilliseconds(200);
// Run the dispatcher for everything over background priority
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => {}));
}
Here is a wonderful blog posting from Dwane Need that discusses all the available options for working with UI elements amongst multiple threads.
You really haven't given enough detail to give a good prescription. For example, why are you creating UI elements yourself at all instead of using databinding? You might have a good reason, but without more details it's hard to give good advice. As another example of detail that would be useful, are you looking to build complex deeply nested control hierarchies for each piece of data or do you just need to draw a simple shape?
I had a similar problem with my panel which was moving its items. The UI was freezing because I was using a DispatcherTimer at priority Loaded. The problem is gone as soon as I changed it to DispatcherPriority.Input.
You can still make your long processing in a separate thread, but when finished you have to synchronize with the UI thread by calling Dispatcher.BeginInvoke(your_UI_action_here)
Recommendations from the OldNewThing blog.
It is best if you do go the threaded route, to have one GUI thread and spawn your work load off to another thread that when finishes reports back to the main GUI thread that its done. The reason for this is because you will not get into thread issues with your GUI interface.
So One GUI Thread
Many worker threads that do the work.
If any of your threads do hang the user is in direct control over your application can can close down the thread without effecting his experience with the application interface. This will make him happy because your user will feel in control other than him constantly click THAT STOP BUTTON AND IT WONT STOP SEARCHING.
Try freezing your UIElements. Frozen objects can be passed between threads without encountering an InvalidOperationException, so you deserialize them & freeze them on a background thread before using them on your UI thread.
Alternatively, consider dispatching the individual deserializations back to the UI thread at background priority. This isn't optimal, since the UI thread still has to do all of the work to deserialize these objects and there's some overhead added by dispatching them as individual tasks, but at least you won't block the UI - higher priority events like input will be able to be interspersed with your lower priority deserialization work.