Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...