Alex Rivera | Logout

How to use multithreading with Winform?

Asked 2011-06-16T09:37:49.333
13

I'm a newbie with multithreading. I have a winform that have a label and a progress bar.

I wanna show the processing result. Firstly, I use Application.DoEvents() method. But, I find that the form is freezing.

Then I read some article about multithreading at MSDN.

Secondly, I use a BackgroundWorker to do it.

this.bwForm.DoWork += (o, arg) => { DoConvert(); };
this.bwForm.RunWorkerAsync();

The form doesn't freeze that I can drag/drog when processing. Unfortunately, it throws an InvalidOperationException. So I have to use this. Control.CheckForIllegalCrossThreadCalls = false; I ensure that's not a final solution.

Do you have some suggestion to do so, Experts?

Edit: When I call listview throw InvalidOperationException. This code is in DoWork().

          foreach (ListViewItem item in this.listView1.Items)
            {
                //........some operation
                 lbFilesCount.Text = string.Format("{0} files", listView1.Items.Count);
                 progressBar1.Value++;
            }

Edit2: I use delegate and invoke in DoWork() and it don't throw exeption. But the form is freezing again. How to do it so the form could be droppable/drappable while processing?

Edit
Report

3 Answers

5

You should use Control.Invoke(). Also see this question for details.

answered 2011-06-16T09:41:11.707
5

Cleanest way is using BackGroundWorker as you did.

you just missed some points:

  1. you cannot access your form elements in DoWork event handler because that makes a cross thread method invokation, this should be done in ProgressChanged event handler.
  2. by default a BackGroundWorker will not allow to report progress, as well as in won't allow Cancelling the operation. When you add a BackGroundWorker to your code, you have to set the WorkerReportsProgress property of that BackGroundWorker to true if you want to call the ReportProgress method of your BackGroundWorker.
  3. In case you need to allow the user to cancel the operation as well, set WorkerSupportsCancellation to true and in your loop in the DoWork event handler check the property named CancellationPending in your BackGroundWorker

I hope I helped

answered 2011-06-23T14:21:45.350
2

Do like this, create a new thread

         Thread loginThread = new Thread(new ThreadStart(DoWork));

         loginThread.Start();

Inside the ThreadStart(), pass the method you want to execute. If inside this method you want to change somes controls properties then create a delegate and point it to a method inside which you will be writing the controls changed properties,

         public delegate void DoWorkDelegate(ChangeControlsProperties);         

and invoke the controls properties do like this, declare a method and inside it define the controls new porperties

         public void UpdateForm()
         {
             // change controls properties over here
         }

then point a delegate to the method, in this way,

         InvokeUIControlDelegate invokeDelegate = new InvokeUIControlDelegate(UpdateForm);

then when you want to change the properties at any place just call this,

         this.Invoke(invokeDelegate);

Hope this code snippet helps you ! :)

answered 2011-06-16T09:57:34.947

Your Answer