Multithreading: how to update the user interface to indicate progress

I have been working on the same project now since Christmas 2008. I was asked to take it from the Console application (which simply prints trace reports) to the full Windows application. Of course, thatโ€™s good. The only thing that is in applications that can take several minutes to almost an hour to run. I need multithreading to show user status or errors. But I donโ€™t know where to start.

I am creating a small user interface in WPF. It is very simple, but I would like to expand it as I need. The application works by choosing a source, choosing a destination and clicking the "Start" button. I want the list to be updated as the process progresses. Just like SQL Server Installs, each step has a green flag by its name as it completes.

How does a newbie start multithreading? What libraries should I check? Any advice would be greatly appreciated.

ps I am now reading about this library, http://www.codeplex.com/smartthreadpool

@Martin: This is how my application is built:

  • Engine: starts all the main components in a predetermined order
  • Excel: a library that I wrote to wrap COM to open / read / close / save workbooks.
  • Library: a library that understands the different types of workbook formats (5 in total).
  • Business Classes: Classes I wrote to translate Excel data and prepare for access
  • Db library: a library that I wrote that uses ADO.NET to read in Access data
  • AppSettings: you get the idea
  • Serial number: save data in case of application failure.

I use everything from LINQ to ADO.NET to get data, convert it, and output.

My basic requirement is that I want to update my user interface to indicate progress

@Frank: what happens if something in the background desktop throws an exception (handled or otherwise)? How does my application receive notification?

@ Eric Lippert: Yes, I'm studying this right now. Before you complicate the situation.

Let me know if you need more information. I am currently running this application from Unit Test, so I assume that its console application is incorrect. I am using Resharper for this. I am the only person who uses the application now, but I need a more attractive interface

+6
multithreading c #
source share
9 answers

I do not think that you indicate the version of the CLR that you are using, but you can check " BackgroundWorker ". This is an easy way to implement multiple threads.

The best part is that it is part of CLR 2.0 and higher

Update in response to your update:. If you want to update progress in the user interface โ€” for example, in the progress bar โ€” the background worker is ideal. It uses an event, which, it seems to me, is called: ProgressChanged, to report the status. It is very elegant. Also, keep in mind that you can have as many cases as you need, and you can run all instances at the same time (if necessary).

In answer to your question : you can easily set up a sample project and check your question. I found the following here (according to the remarks, the 2nd paragraph from caution):

If the operation raises an exception that your code does not handle, BackgroundWorker catches the exception and passes it to the RunWorkerCompleted event handler, where it appears as the Error property of the System.ComponentModel .. ::. RunWorkerCompletedEventArgs.

+6
source share

Threading in C # by Joseph Albahari is not bad.

+4
source share

The best way for a beginner to beginners is probably threadpool. We probably need to know a little about these details in order to make more detailed recommendations.

EDIT ::
Since we now have a little more information, I'm going to stick to my previous answer, it seems that you have a lot of tasks to do, the best way to complete the load of tasks is to add them to threadpool and then just keep checking if they are completed if tasks must be performed in a specific order, then you can simply add the next one, like the previous one. Threadpool is really pretty good for this kind of thing, and I see no reason not to use it in this case.

0
source share

This page is a good summary of threads.

By the sound of this, you probably donโ€™t need anything very complicated - if you are just starting a task and then want to know when it is finished, you only need a few lines of code to create a new thread and get it to complete your task. Then your UI thread can fling and periodically check if the task is completed.

0
source share

Concurrent programming on Windows is the best existence book on this subject. Posted by Joe Duffy, the famous Microsoft Guru for multithreading. Everything you need to know and much more, starting with how the Windows Thread Scheduler works in the Parallels .NET Extensions Library.

0
source share

Do not forget to create your delegates to update the user interface, so that there are no problems with cross-threads, and the user interface is not displayed for blocking / blocking

Also if you need a lot of notes / power points / etc, etc.

Can I offer all lecture notes from my teenager? http://ist.psu.edu/courses/SP04/ist411/lectures.html

0
source share

Jason Link is a good article. The things you need to know about is that the user interface can only be updated using the main user interface thread, you will get cross-threading exceptions if you try to do this in the workflow. The BackgroundWorker element can help you with events there, but you should also know about Control.Invoke (or Control.Begin / EndInvoke). This can be used to run delegates in the context of a user interface thread.

You should also read about how to access the same code / variables from different threads, some of these problems can lead to errors that are intermittent and difficult to track.

It should be noted that the volatile keyword only guarantees "freshness" of access to the variable, for example, it ensures that each reading and writing of the variable will be from the main memory, and not from the thread cache or processor or another "function" of the memory model. It does not stop problems such as a thread interrupted by another thread during the read-update-write process (for example, changing the value of variables). This leads to errors when 2 threads have different (or the same) values โ€‹โ€‹for a variable and can lead to the loss of things like values, 2 threads having the same value for a variable, when they must have different values, etc. You should use a lock / monitor (or other thread synchronization method, wait mechanisms, interlockedincrement / decment, etc.) to prevent these problems, which ensure that only one thread can access the variable. (The monitor also has the advantage that it implicitly performs volatile read / write)

And, as someone else pointed out, you should also avoid blocking the user interface thread while waiting for the background threads to complete, otherwise your user interface will stop responding. You can do this if your workflows raise events that are signed by your user interface to indicate progress or completion.

Matt

0
source share

Typemock has a new tool called Racer for multithreading assistance. Its a bit advanced, but you can get help on your forum and other online forums (which strangely comes to mind - stackoverflow :-))

0
source share

I'm new to multithreading too, but I agree with Frank that a background worker is probably your best bet. It works through event subscriptions. Here is basic information about how you used it.

  • First create a new background worker.
  • Signed methods in your code for the main participants in the main events:
    • DoWork: it should contain any code that takes a long time to process
    • ProgressChanged: it is called whenever you call ReportProgress () from a method subscribed to DoWork
    • RunWorkerCompleted: called when the DoWork method completes

When you are ready to complete your time-consuming process, you call the RunAsync () method of the desktop background. This will launch the DoWork method in a separate thread, which can then report this during the ProgressChanged event. After its completion RunWorkerComplete will be called.

The DoWork event method can also check whether the user has somehow requested a process cancellation (CancelLAsync () was called)) by checking the value of the CancelPending property.

0
source share

All Articles