I have to render about 10'000 wpf controls, and I don't want to freeze my application during this action. Is it possible to do it in another thread?
I tried to use
myStackPanel.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.SystemIdle,
new NextPrimeDelegate(this.AddButton));
and another variants of Dispatcher. But it always freeze my application. I'd like to show animated waiting screen during creating hundred controls, but it's always freeze, because it's dispatcher's thread.
thanks for help
Andrew.
WPF controls must be created on the thread associated with the dispatcher where they will be presented. The call to Dispatcher.BeginInvoke schedules the specified action to run on the dispatcher thread at a later time, not on a background thread.
If you have a lot of UI controls to create and want to display an animation during their creation, then you will need to segment the work to be done into small units that can be quickly processed. You can then call BeginInvoke at a priority lower than normal to process each unit of work group individually.
The fact that you need to create 10,000 controls is extreme and you should probably investigate virtualizing the controls.
Related
I am currently developing an ASP.NET application. I need to access certain controls like labels or textboxes through a non-UI thread, I am not able to do so. Could someone point me in the right direction? Even Response.Write doesn't seem to work.
By non-UI Thred, I mean a worker thread since loading of the UI is usually done by the main thread. I need my worker threads to be able to access controls like labels or textboxes to change their .text properties.
Alternativly, you can use the BackgroundWorker class to execute some task in background.
BackgroundWorker will give an event ProgressChanged, use this ecent to write/update controls value on UI thread.
I need to measure the performance of WPF multi-threaded application, what happens is following:
1. buttonClick is triggered in UI -> the UI thread starts processing it
2. UI thread starts another threads in background, which asyncronously do something in background and, when ready, pass the result back to the ui thread
3. Data binding occurs
4. Rendering occurs
The amount of threads is known to me, the order is not.
How could I measure the time between the buttonClick and the end of the rendering? Is the UI thread firing an event or raise a property when it has finished? Or if not, can I make it?
Any help would be apprechiated.
I found something possibly helpful at http://www.kynosarges.de/WpfPerformance.html:
We cannot directly access the rendering thread but WPF does offer one
indirect point of access, namely through the
CompositionTarget.Rendering event. This event usually fires at the
monitor refresh rate (typically 60 times per second), whether there’s
any new content to render or not. It is primarily intended for custom
animations that need to generate display updates as quickly as the
monitor can show them.
You have to look on WPF Performance Suite, especially on Perforator and Visual Profiler.
On VisualProfiler you can have "Application CPU usage details" section one of which is:
Render (MediaContext) Occurs during the render pass. This method
eventually calls the OnRender method of each element, and is useful
for understanding the total cost of OnRender for all elements....
or
Rendering Thread Occurs when executing rendering instructions on the
rendering thread. This is useful for detecting render-bound
applications.
Hope this helps.
In my Silverlight application, I have an operation that takes a couple seconds and strongly interacts with the GUI (creation of display objects in a big "for" statement)
At first I thought of using the BackgroundWorker to avoid freezing the interface. But I cannot update the GUI directly, so I used the Dispatcher.BeginInvoke, but it still freezes the interface (since the long actions are on the gui part).
What I'd want is display a BusyIndicator while it loads my objects but I want the user to be able to continue working while it loads.
What else can I do? Any suggestions?
Even a busy icon won't help you here. Busy icons, or any other graphics item, require the UI thread to pump messages in order to not "freeze" the UI. If your long running operations are running on the UI thread then even the busy cursor will "freeze".
You need to either
Move the expensive long running logic to a background thread
Break up the UI logic into chunks and let the UI refresh in between them.
Creating UI items in the BackgroundWorker is just wrong. Creating UI elements requires switching back to the UI thread if run from a BackgroundWorker. That is just making things worse than creating them on the main thread.
I assume that lots of the work in the BackgroundWorker is not creating the elements but some additional processing that happens to create UI elements in the middle of everything else.
If that is the case you need to break out the actual generation of UI elements. Replace the generation of UI elements with dummy-classes that contains all specifications required to build all elements. Then you return that collection of specifications (the dummy-classes) and generate the actual elements in the BackgroundWorker.RunWorkerCompleted event.
i have a class which, when a certain part of the gui is clicked will
-create a backgroundworker and do the following taks
-create a new object(this is a new windows form)
-call a method on it which gets some data
-populate the new windows form gui with that data
The problem is there is a gui component on the form which cant be created from outside of the main programme thread, if i do try i get the error
Active x .... cannot be instantiated because the
current thread is not in a
single-threaded apartment.
is there help people can offer so i can structure this?
in my do work
Don't create GUI components in a background thread. Use the background thread to get and process data, then render them in the UI in the main thread. I know that this in inconvenient, because
creating lots of UI elements can also take a lot of time and
creating them in the UI thread requires you to split your code into UI part and data processing part,
but there's not really a way around it. .NET UI components are not designed to be handled in background threads.
To perform only certain operations of your code in the main thread, you can use
someUIControl.Invoke(...) (WinForms) or
Dispatcher.Invoke(...) (WPF)
in the DoWork event handler of your BackgroundWorker. Alternatively, you can perform the UI operations in the RunWorkerCompleted event handler of your BackgroundWorker, which always executes in the UI thread.
The UI should only be managed by the UI thread.
One possible solution would be to load the data asynchronously with the BackgroundWorker, and when it is done use the Result property of the DoWorkEventArgs to pass the results back to the UI thread and then display the new form.
My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.
I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?
What would you do in this particular case?
If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.
The basic pattern is:
Invoke your primary task, passing in zero for the step.
Perform the step.
If there are more steps, queue another message, passing in step + 1.
You can then add in progress updates at the appropriate points in your code.
PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.
It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.
This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.
Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).
I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).