Create or load controls without freezing the window - c#

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.

Related

WinRT XAML UI stalls even though using background thread

I have an app where activities that aren't likely to finish quickly are run on a background thread. For example, I have some items to display where I show a generic icon to begin with while the background code tries to see if there is an associated image that should be displayed instead.
When XAML tries to fetch the image, if I don't have it already, I add the query to a queue for later processing and temporarily return null. The queue handling basically does this:
Get a mutex (so that I can manipulate single items safely)
If the item isn't already in the queue, add it
If the queue isn't already running, start it
Release the mutex
The queue is run with this:
objectFileQueueRunning = true;
cts = new CancellationTokenSource();
Task.Run(() => ProcessObjectFileQueue(cts.Token));
The queue code basically keeps on taking the top item off the list and processes it until we run out of items or the cancellation token gets set. The same mutex is used within the queue code but only when removing the top item off the list and when resetting objectFileQueueRunning to false.
My problem is that the UI thread is basically unresponsive until the queue code finishes running ... even though it is running on a background thread.
I've run performance analysis on the executing app but cannot spot anything that would seem to give me any hints as to what to look at.
Do I need to put a pause into the background thread to give the UI thread a chance to interact with the user? Is it the case that I'm running the background thread so tightly that the UI thread isn't getting a look-in?
The solution, in my case anyway, turned out to be the use of StackPanel as the ItemsPanelTemplate coupled with the background thread doing a lot of work.
The problem with using StackPanel is that it causes virtualisation to be disabled, which means that all of the elements get created in one go.
Switching to ItemsWrapGrid allows GridView to use virtualisation and therefore only create elements that are either visible or about to become visible. This, in turn, causes the background workload to be reduced.
The reason I was using StackPanel dates back to when my app was first written for Windows 8.0. Using the default settings caused problems when the user scrolled horizontally because the scroll bar size would vary. This seems to have been fixed in Windows 8.1 but I hadn't thought to revisit the XAML as I updated the app.
Shared in case anyone else hits similar issues.

C# How to implement Threading or BackgroundWorker tasks

I can't seem to figure out how to use either the threading or Backgroundworker task. My problem is that I am loading a large XML file into a TreeView and would like to display a progress bar while doing so. The issue right now is that the app freezes when it's loading and says the app is non-responsive.
Threading / Background worker tasks is new to me so I am not exactly sure how to make this work.
First we will start with my button to get the user details
So we get the users's details and call CreateXML for the user detail object. So we have the XML in one big string called strXML. Then I call dom.LoadXml to load xml sting into the dom object. Then we initialize the tree view control and add the nodes etc.
So during this whole process the app hangs and indicates that it's not responding while it's busy churning thought the XML and creating it into a treeview. I want to put in a progress bar so the end user see's that something is actually going on and they don't think the app just died on them.
How would i implement some sort of progress bar with a thread or back ground worker?
Please just don't redirect me to link after link because that never really works for me.
Thanks
I was able to implement multi-threading which then I was able to achieve the progress bar moving while the data was being loaded. Sometimes people need to wait for data to be loaded and a simple indicator is all that's needed so users know the app is working.

Why do some Windows UI elements update immediately and others do not?

We have a button click event that starts a long running task that updates the status bar labels and progress control to give user feedback. Before we moved the task to a seperate thread we noticed the status labels {label.text = "some message"; }(in general) would update immediately while the progress bar and some custom controls often would not update until the function finished and the main UI thread started sending messages again ( which we realized makes sense considering the main UI thread).
But this lead us to wonder - Do some windows controls repaint directly instead of being issued a WM_Paint message?
Your findings are pretty contradictory from what I know about .NET controls. The common rule is that changing the Text property or altering a property like ForeColor or BackColor merely causes the Invalidate() method to be called. Which ultimately causes a WM_PAINT message to be delivered when the UI thread starts pumping messages again. You can call the control's or the Form's Update() method to force any pending paints to be performed before entering the slow code. This is all entirely standard Windows behavior.
A special case is the ProgressBar control. The native Windows implementation for it updates the bar length directly. That's compat behavior, this control often is used in code that doesn't pump properly.
TextBox has special painting behavior, it partly paints directly to the window instead of going through the WM_PAINT message handler. That's legacy behavior way back from Windows 2 when it needed to work reasonably on a 386SUX machine. But that's not relevant in this case.
Of course, rather than fretting about this you should just never get yourself in a place where any of this matters.

How can I make a loader animation that runs while code executes?

I have a page that runs a large amount of code to prepare the page and layout of the page for the user.
It only needs to be used once in a blue moon. But when it does, it's about three seconds of wait for the user.
Apparently, Microsoft only allows a 2 or less second wait. Daaaaang.
I've optimized and optimized the code, and there's no way around it: the code is as fast as it can be. So naturally, I set out to make a loader.
I tried to update several controls, but thanks to the UI thread being frozen, they didn't work.
I searched and searched and searched, and found this, which was confusing and didn't really help, partly because of WP7's version of C# and partly because of me being a beginner at C#.
How can I make a loader that works while the UI thread is frozen?
The Silverlight Toolkit For Windows Phone introduces the PerformanceProgressBar, "which uses the compositor thread exclusively for animation, instead of the UI (user interface) thread" as described in this WindowsPhone Geek article. This should help you with the freezing UI.
As of the parallel execution (suggested by Merlyn), I'd suggest the QueueUserWorkItem method to execute code in a separate thread over the BackgroundWorker, leaving the UI thread active for UI updates, but as described in the article, you will need to use Dispatcher.BeginInvoke to update your UI from there.
You can try using the BackgroundWorker class. That page has a tutorial for how to use it.
See this question and my answer for another tutorial. Though not Windows Phone 7 specific, it still has to do with updating the UI while waiting for a task to complete:
How To Load UI Independent Of Data
Here's a Windows Phone 7 specific tutorial for using the BackgroundWorker:
http://blogs.msdn.com/b/priozersk/archive/2010/09/20/creating-progress-dialog-for-wp7.aspx

Ok to use a C# Panel's HWND in a Win32 Dll on another thread?

I have something working but I'm not sure it is OK and if it will cause problems later on.
I have a Win32 C++ app which does some video processing and uses Direct3D for display (not my code). My task is replacing the GUI with a C# GUI.
I've made the C++ code into a dll.
I've created a GUI in C# and have a panel intended for the video-display. I pass this panel's HWND to the dll, and everything seems to work just fine.
But - that panel is being accessed by a thread other than the one it was created on, which shouldn't be done.
Part of me wants to "leave well enough alone" but this feels wrong and I suspect it will cause problems down the line. Such as when we want to catch click-events on the panel, which will be on the main or UI thread ... which created the panel.
ANy suggestions on how I should be doing this?
Thank you
Thanks
I think you already know the answer to this. Windows have thread affinity. All operations on a window should be performed from the thread that created it.
Given this rule, I can't imagine that the DLL is responsible for moving window access onto a different thread and presume it is your code that does it. The solution is for you to create and access the window in the same thread that calls the DLL.
The main problem I've seen with this technique is that your UI can flicker. If you are early enough in the process to use WPF you may want to take a look at D3DImage if not what you are doing now will mostly work.

Categories