Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use multithreading with Winform?

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?

like image 607
Justin Avatar asked Jun 16 '11 09:06

Justin


People also ask

Is WinForms multithreaded?

The . NET Framework has full support for running multiple threads at once.

Is WinForms dying?

Win Form has been used to develop many applications. Because of its high age (born in 2003), WinForm was officially declared dead by Microsoft in 2014. However, Win Form is still alive and well.

Is multithreading possible in C#?

Multithreading in C# is a process in which multiple threads work simultaneously. It is a process to achieve multitasking. It saves time because multiple tasks are being executed at a time. To create multithreaded application in C#, we need to use System.


1 Answers

You can only set progress bar user control properties from the UI thread (the WinForm one). The easiest way to do it with your BackgroundWorker is to use the ProgressChanged event:

private BackgroundWorker bwForm;
private ProgressBar progressBar;

In WinForm constructor:

this.progressBar = new ProgressBar();
this.progressBar.Maximum = 100;
this.bwForm = new BackgroundWorker();
this.bwForm.DoWork += new DoWorkEventHandler(this.BwForm_DoWork);
this.bwForm.ProgressChanged += new ProgressChangedEventHandler(this.BwForm_ProgressChanged);
this.bwForm.RunWorkerAsync();

...

void BwForm_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bgw = sender as BackgroundWorker;
    // Your DoConvert code here
    // ...          
    int percent = 0;
    bgw.ReportProgress(percent);
    // ...
}

void BwForm_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.progressBar.Value = e.ProgressPercentage;
}

see here: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

EDIT

So I didn't understand your question, I thought it was about showing progress bar progression during work. If it's about result of work use e.Result in the BwForm_DoWork event. Add a new event handler for completed event and manage result:

this.bwForm.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BwForm_RunWorkerCompleted);

...

private void BwForm_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    YourResultStruct result = e.Result as YourResultStruct;
    if (e.Error != null && result != null)
    {
        // Handle result here
    }
}
like image 183
Vince Avatar answered Oct 04 '22 12:10

Vince