Write status messages to a textbox asynchronously? - c#

I recently started programming in WinForms using C#. I have a requirement where I need to search a set of folders and the sub-folders and display the status information to a textbox as I do the search like -
Looking up folder "C:\Windows"...
Found 8 files...
Copying file 1 of 8 to "D:\Temp"...
I have a method which does all the searching and stuff. I don't know how to display the status messages (like above) to a textbox periodically. Currently, the form waits for the method to be complete, and displays the messages all at once. I want them to be displayed one by one as the method progresses.
Thanks in advance.

To properly solve this your searching function will need to be running on a background thread. If the searching occurs on the UI thread it will block updates to the display preventing a periodic status message from being displayed.
The easiest way to do this in a WinForms application is to use a BackgroundWorker. It has a minimum of support for running a task on a background and returning progress information to the UI thread. Additionally there are a lot of tutorials available online to get you started with a solution.

use a BackgroundWorkerThread and the ReportStatus function. That way your UI will be responsive while the search takes place.

Run the method that performs searches on a separate thread (if you're not doing so already). It's quite easy using the async delegate features in .NET.
You can then write to the text box from the worker thread using Control.BeginInvoke() - you must do this because access to UI control sis affinitized to the single UI thread.
You can also create a background worker thread and use the ReportProgress method to notify the UI of updates. There's a fairly complete example of this approach available here that you can download and examine.

Related

How to control a separate WPF application?

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.

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.

How do i display a progress bar while loading a datatable to DataGridview?

I have a method called GetAllRecords() that will return a datatable of 200K records. When I checked it took about 5 seconds to load data to the datagrid and window froze.
DataTable dt = Records.GetAllRecords();
I know I have to use Background worker controls and it's three events, but I cannot figureout how to use them properly. For instance, the progress bar must show real progress not a fake one. I could slow the progress bar using sleep() of the thread class but it would be a fake progress bar.
Could any one here please give me step by step instructions on how to create a real progress bar on my windows form?
Before .NET 2.0 there was not Background worker control, in those days how programmer wrote real progress bars?
thanks
If you do a search of the site, as well as Google, you'll see that there are several attempts at doing this:
SO Link
MSDN Link
These solutions basically update the progress bar after you add each row to the grid, though if you're trying to show progress for an actual database call I don't think you'll be able to be very accurate on that.
I think the main problem you'll have is that you won't have event hooks to let you know exactly where the time-consuming part of the binding comes into play. I'm assuming that it takes 5 seconds once you bind the data to the grid and that you're not counting the load time of actually pulling down the records.
Pre-BackgroundWorker
The BackgroundWorker class is basically just a convenience to you handling the threading yourself and invoking any progress back to the UI thread for you. You would have to spawn your own thread, and call BeginInvoke on your control once work is done to apply the data to the UI thread, since you can't make changes to the UI on any thread but the main one.
For the basics on how to implement a BackgroundWorker and a ProgressBar you can consult the examples given in the MSDN pages for ProgressBar and BackgroundWorker
As for actually making the percentage completed-property of your ProgressBar make sense, the key lies in finding a meaningful value to use as the argument for BackgroundWorker.ReportProgress(int). As you have probably noticed, in most tutorials and examples, people will normally just do a Thread.Sleep(100) inside a for-loop from 1 -> 100 and then send the iteration variable as the argument to ReportProgress.
The easiest solution for you is probably to set the ProgressBarStyle property to Marquee. That way your users can rest assured that your application hasn't frozen and that progress IS being made, although they won't know how long it will take for the operation to complete.

How To Scan Files and Show Details of Current Scanning Without Making The Application Non-Responsive?

I am developing a desktop application for pdf file management using C#.
When I search any folder for *.pdf the application stops responding for some time, which is undesired behavior.
I am using XmlWriter to write data (i.e. file name,author name,subject). Also I have a label to show current scanning of file but it only show last file after complition of scanning.
This is a classic problem.
Basically the thread which displays the application is the thread which is doing all the work. So any updates/responsivness of the GUI will have to wait until its finished.
The solution to this is to make it multithreaded. The simplest way is to use a Background Worker thread which will do the writing searching and whatever, and just leave the main thread free.
http://www.dotnetperls.com/backgroundworker
If you can update your program, .NET 4.0 has new IO functions that return before finishing:
For example EnumerateFiles:
http://msdn.microsoft.com/en-us/library/dd383458.aspx
In addition to Haedrian's answer, I'd say that you could use the ProgressChanged event of BackGroundWorker to handle updating your progress indicators.
More specifically, you could raise that event with ReportProgress method, passing the name of the file curently scanning, and in the BackGroundWorker.ProgressChanged event handler you could update the label you want to use to show the file under scanning
If you don't like to create an extra thread you can call
Application.DoEvents();
in the loop. This keeps application responding and updates the label.

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

Categories