My project requires a background thread to initiate the creation of a WPF control hosted in a Winform. The creation of said control must be performed on the foreground thread, which is very costly and causes the UI to hang for 1 to 2.5 seconds (depending on whether this is the first time the control is created).
Are there any pre creation optimizations that can be done from a background thread to reduce the amount of work done by the UI thread?
I assume you use the ElementHost control to host the Wpf control in the winforms app? I think the overhead you're seeing is really necessary, as the device context the wpf elements are rendered on is marshalled to the winforms app and isn't living in a normal wpf application. My experience is that when you open a form with ElementHost on it, the second time is much faster, but of course it depends on what you're doing when it opens.
Related
I'm developing a Revit add-on which performs some lengthy tasks. During the process, I want to display a simple WPF window with an indeterminate progress bar, a label to inform about current process and a button to enable aborting.
I already tried the most obvious ways of accomplishing that: creating a WPF window inside the add-on and displaying it, but the problem is that the UI gets frozen, no matter how I implement this. During some processes, the whole Revit UI gets frozen/white so I really wouldn't expect my embedded WPF window would behave normally in these conditions anyway.
The workaround I figured out was to have the WPF window as a separate app (EXE file) I could run from the add-on. I based my implementation on this example .
The good part of it is that it doesn't hang no matter what is happening with Revit.
The bad part is that the sequence of how Windows is queuing the calls of my separate WPF app is sometimes different from the sequence of these calls from my add-on. It sometimes results in a situation when the Revit process is over but the WPF window is still displayed (waiting for the final, closing call which had been apparently already executed, but then the app got reactivated with another, delayed call).
Preferably I would like to handle the WPF app the same way as you can i.e. handle an Excel application from .NET. You create an ExcelApp object, do what you want with it and dispose of in the end.
The problem is I don't have a clue of how to do this.
How should I expose the WPF app's API to my add-on?
Could it be possible to have the WPF app responsive and controlled from the Revit add-on at the same time? (user can still click the abort button, the indeterminate progress bar doesn't freeze)
The First thing to know is about interacting between two processes. there are some Standard approaches:
Interacting through Socket (Socket Programming)
Using Named PipeLines (Useful when your messages aren't so long)
There are some other predefined Libraries based on above techniques. Using a FileSystem Based method is not a reliable way to proof the outputs.
This was a part of your solution. The next step is to use Threading in your WPF application. I'm not familiar to Revit and I don't know how it works.
UI freezing is normal in a long running process. because UI is busy and it can't answer your requests (e.g Mouse Move, Click, ...). So using a Thread you can put your long running process into a separate place and wait for the response at the end of it.
There is a problem while using a Thread. Because you left your UI and started your long running process on a separate Thread, you can't directly access to your ProgressBar. In this situations you have to use ThreadDispacher. It's not a terrifying concept, it just a three line of codes that will adds to your callings.
for example:
Dispatcher.Invoke(() =>
{
ProgressBar.Value++;
});
Search for a Library to doing your IPC (Inter Process Communication) to get the result faster (or you can learn about above techniques to do it by your means) and next add a simple thread to your WPF application so you be able to Start, Pause and resume the running job based on the situation.
I have a WPF application. I would like to explain the working of the application. The application is used for monitoring data that is received over network through UDP, every 100 ms. In the application's main window, another thread is started in which the UPD packets are received and parsed. After the data is parsed, the packet based on packet ID is updated to UI through dispatcher. There are 5 windows with a browser control, couple of charts and text boxes in each window.
The UI rendering is slow and application responsiveness reduces when more than one window at a time is updated. What is the best way to improve the performance of the application? Is it good if each of the window is created in a new thread? If each window is created in a new thread, I have noticed that some data is missing in the UI. Moreover, setting the owner of these windows to the main window is also not possible which is proving to be a problem.
I have a WPF application with two windows. One window contains a WebBrowser control. The other window contains a WindowsFormsHost which hosts a WinForms Chart control for drawing a line chart. I tried with charting provided by WPF Toolkit, but the memory consumption is increasing. I am displaying a local HTML file with javascript to show a location on Google Map. The location is updated every 100 ms. Along with the location, some other data is received which I have to display on the Line Chart.
While testing, I have observed that the graph and browser both are updating well simulataneously with 500 ms interval. But when the frequency is changed to 100 ms, the browser stops updating. It is also observed that if data plotting on the chart is stopped, the browser tiles load back again and location is updating.
Any hint as to what the problem might be??
This sounds like a classic example of either a very busy main thread (UI thread) that is updating the chart is starving out main thread updates to the web browser control. Or if you have separate threads, other than the main thread, updating the chart and the web browser, again the I/O latency updating the chart is short compared to the I/O latency updating the web browser and therefore the chart update thread is starving out the web browser updates. Even if the web browser updates and the chart updates are sourced from separate threads, other than the UI thread, one thread can starve out the other. There too many ways to fix this to list here. You just have to make sure the threads doing the updates to the chart and web browser control have an balanced/equal chance to get a time slice to do their thing.
When a browser is opened, before it's completely loaded, we can use the controls as others are being loaded (the address bar appears and, while the bookmarks are loaded, we can already type in it).
I'm making a personal browser, and I don't know how to perform that. I imagined creating the controls in another thread, but soon I discovered that that's not possible.
In my last question (where I discovered the above), I received an answer talking about Attribute, Reflection, async/await modifiers and observable collection as the closest solution to that and I'll study them yet. In this new question, I would like to receive others suggestions of how that could be made (allow the user to use the window and controls while others are being created/loaded).
Thanks in advance.
Actually I believe the process of loading the UI part of controls isn't the heavy one.
In the other hand, loading the data which is later bound to the control is the problem.
You can't draw controls outside UI thread, but you can load heavy data, preload resources or do calculation in a background thread.
While heavy controls' data is prepared to hit the UI in some background thread, UI will still be responsive.
For example, I guess Web browsers do HTML to DOM parsing in a background thread and they stream results in real time to the UI thread. That is, address bar and other UI components are responsive because UI thread isn't stressed.
I am trying to make a windows form appliation that displays all the Tasks that are running while they are running. I want to stop tasks individually if I want to. I have the application working as a console application but when I try to build it as a windows form application it screws up. Here is how my code works.
Loop
Make a task
store it in a list
start the task=
End Loop
I want to display this list in a listView in my form and update it every few seconds displaying the name and status of this task.Can somebody help me with that or suggest good reads to study multithreading.
Thanks.
I have the application working as a console application but when I try to build it as a windows form application it screws up.
Provided that you didn't change your logic during the port to Windows Forms, this is likely due to updating the Windows Forms controls from the background thread within your Task.
You can only use Windows Forms controls from the main (UI) thread, and not from a background thread. If you want to perform an update to the UI, you need to use Control.Invoke or Control.BeginInvoke to marshal the call back onto the UI thread.