The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Multithreading help with books / easy tutorials

Hi Guys,

I have a product thats out of beta and has been selling for the last 2 months..  It sells but some people get the impression that the program is slow.

Because it works with lots of photos it takes time to process them. 

Its not multithreaded so when its working GUI freezes..  giving the impression of freezing or slowing down.

I need a bit of direction..  Is it hard to convert it to multi threaded app so that the processes are done separate from the GUI thread.

I know it will take a bit of work to learn and then conver my app..  But is it easier to rewrite the whole app from scratch as multithreaded or just thread some of the heavy functions. 

Any of you know of books / video tutorials that has helped you learn multithreading for  VB.NET ?


I only know vb.net so I'd like to stick to it.

Thanks everyone
Threader
Wednesday, June 13, 2007
 
 
Multithreading for the sole purpose of unblocking the GUI thread is easy, assuming you want to put the program into a 'locked' state while processing.

Not sure how you do it in VB.Net, but theoretically all you need to do is make the following changes:

1. Move the offending blocking code to it's own function.
2. Change the current function to lock the GUI and spawn a thread to run the function.
3. Create a callback function to re-enable the GUI and display the result / continue processing.

Wednesday, June 13, 2007
 
 
How hard this will be really depends on the way your app is written. 

Making a long-running method that's blocking the UI run asynchronously is one of the easier cases of multithreading to implement.  If you have a long-running method that runs when the user clicks a button or selects a menu item, it's very straightforward to run that on a separate thread using BackgroundWorker. 

It gets less straightforward if your method is updating the GUI as it goes, because the BackgroundWorker thread can't touch the GUI directly.  It's still not terrifically hard to implement, but you have to learn about using Invoke() to communicate with the GUI thread.

Of course, you will now have to write code to handle states that your program couldn't get into back when your method was blocking the GUI thread - at a minimum, you have to disable any controls that let the user run methods which use the same data that the DoWork method is using. 

The other thing you need to know is that if your method throws an exception, the thread will just silently die.  So you need to be sure you handle exceptions that might get thrown on that thread.

Take a look at the help for BackgroundWorker.  You may find that you can just plow in and start using it.
Robert Rossney Send private email
Wednesday, June 13, 2007
 
 
There are no really good tutorials about - I know because I am going through the same process as yourself at the moment.

As usual, I found it difficult to come to grips with the theory and then implement it without conflicts occuring.

The concept of "Background" means that it has no user interface and doesn't interfere with the "Forground" worker which is of course what the user sees and interacts with. If you want the user to see that something is happening and your program hasn't crashed then I implemented a status strip, statuslabels and progress bar. As the processing continues, then just change the labels text and progress bar steps. You do NOT need to do this with threading. For example, if your project processes say 10 photos then just change the label/progress bar when your function loops through them. One trick though - you will need to have statustrip.refresh() after your code to update the label/progress bar otherwise it won't be updated on the viewable form.

So far, my attempts to update a listview in the viewable ("Foreground") form by having a background process parse thousands of lines of text fails dismally with a conflict on the very first line to call listview.item.add !!

If you need a process to complete before the user can interact with your program then threading seems to be pointless. I guess you can incorporate a game of chess to run in the foreground thread while the program processes your photo's in the background might work :-)

There's a good video presentation on the backgroundworker here  http://www.infoq.com/presentations/windows-forms-tips-tricks .
Glen Harvy Send private email
Wednesday, June 13, 2007
 
 
I found http://www.skeet.org.uk/csharp/threads/ to be a good tutorial.  It covers the basic terminology and how-to.  Enough at least to wrap your head around concepts.
tjk Send private email
Wednesday, June 13, 2007
 
 
Glen,
my app runs just like you described with text and progresbar

and updates after each image process.. works fine..  untill a users starts to frantically clikcing on the application :)


then it just freezes..  but still processing in the background and comes back to life when all is finished.

but app goes white and looks like it crashes..  users get impatient.

its a long process and upload  function
Threader
Wednesday, June 13, 2007
 
 
> One trick though - you will need to have
> statustrip.refresh() after your code to update the
> label/progress bar otherwise it won't be updated on the
> viewable form.
>
> So far, my attempts to update a listview in the viewable
> ("Foreground") form by having a background process parse
> thousands of lines of text fails dismally with a conflict
> on the very first line to call listview.item.add !!

That's because you're not using Invoke. 

Here's an example.  Create a button, a ListView, and a BackgroundWorker on a form (using the default names for each), and set the BackgroundWorker's DoWork event.  As you'll see, during every iteration of the loop in backgroundWorker1_DoWork(), the method "parses a line of text" and adds it to a List<string> called MyList. 

Then it invokes an event handler on the form.  This event handler is running in the UI thread, and so it can manipulate the contents of the ListView.  The result is exactly what you want:  a ListView whose contents are being updated as your background task finds new items for it.

    public partial class Form1 : Form
    {
        private List<string> MyList = new List<string>();

        public Form1()
        {
            InitializeComponent();
        }

        public void UpdateListView(object sender, EventArgs e)
        {
            for (int i = listView1.Items.Count;
                    i < MyList.Count;
                    i++)
            {
                listView1.Items.Add(MyList[i]);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                string s = ParseNextLine();
                if (s == "") break;
                MyList.Add(s);
                this.Invoke((EventHandler)this.UpdateListView);
            }
        }

        private string ParseNextLine()
        {
            if (MyList.Count >= 1000)
            {
                return "";
            }
            return String.Format("Line {0}", MyList.Count + 1);
        }
    }
Robert Rossney Send private email
Wednesday, June 13, 2007
 
 
Background worker has ReportProgress which is for updating GUI, etc.
Ruatara P Send private email
Wednesday, June 13, 2007
 
 
I took the harder approach.

learning how to create own new thread and process data.. and write to GUI..

works quiet well so far.. :)  about 2 hours of learning
Threader
Thursday, June 14, 2007
 
 
"Principles of Concurrent and Distributed Programming, 2nd Ed", Ben-Ari, 2006.

It used to be called the Igloo book, but it doesn't have igloos on the cover anymore.
Katie Lucas
Thursday, June 14, 2007
 
 
>> I only know vb.net so I'd like to stick to it. <<

The sample chapter from my latest book covers multi-threading in .NET 1.x, and specifically VB .NET. But it was written before .NET 2.0, so it doesn't cover the BackgroundWorker type.

You can find the sample chapter here:
http://www.apress.com/book/bookDisplay.html?bID=128
Mark Pearce Send private email
Thursday, June 14, 2007
 
 
>> That's because you're not using Invoke. <<

You should use BeginInvoke rather than Invoke wherever possible because it's less prone to deadlock. Because Invoke is synchronous, it blocks the worker thread until the UI thread becomes available.

For example, if the UI thread is waiting for the worker thread to do something, your app will deadlock. BeginInvoke avoids this since it never waits for the UI thread.
Mark Pearce Send private email
Thursday, June 14, 2007
 
 
Even if you don't add multi-threading, adding a progress bar or some animation during the upload will give the perception that it is running fast.
OneMist8k
Sunday, June 17, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz