简体   繁体   中英

Windows Form Embedded Progress Bar Background Worker

I would like to use a progress bar in the form but am having issues.

On form load, the progress bar completes and the list view populates with icons for the "connected" devices.

When I try to select another index in the list of network adapters, the progress bar and list view clear but an exception is thrown and nothing happens in the GUI.

Exception thrown: 'System.InvalidOperationException' in System.Windows.Forms.dll

I'm assuming this is a threading issue but I have no idea.

Here is the codes, any help or advice is much appreciated.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class ConnectDialog : Form
    {
        BackgroundWorker bkgndWorker = null;
        Dictionary<string, int> dictionary = new Dictionary<string, int>();
        ImageList deviceImageList = new ImageList();

        public ConnectDialog()
        {
            InitializeComponent();       
        }

        public ConnectDialog(List<String> ipAddr)
        {
            InitializeComponent();
            cboNetworkAdapter.Items.AddRange(ipAddr.ToArray());
            cboNetworkAdapter.SelectedIndex = 0;
        }

        private void ConnectDialog_Load(object sender, EventArgs e)
        {
            Bitmap devImage = Properties.Resources.devIcon;
            deviceImageList.Images.Add(devImage);
            deviceImageList.ImageSize = new Size(30, 30);
        }

        private void cboNetworkAdapter_SelectedIndexChanged(object sender, EventArgs e)
        {
            StartWorking();
        }

        private void StartWorking()
        {
            prgBarConnect.Value = 0;
            dictionary.Clear();
            lstvwDevIds.Clear();
            bkgndWorker = new BackgroundWorker();

            bkgndWorker.DoWork += new DoWorkEventHandler(bkgndWorker_DoWork);
            bkgndWorker.ProgressChanged += new ProgressChangedEventHandler(bkgndWorker_ProgressChanged);
            bkgndWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bkgndWorker_RunWorkerCompleted);
            bkgndWorker.WorkerReportsProgress = true;
            bkgndWorker.RunWorkerAsync();
            bkgndWorker.Dispose();
        }

        private void bkgndWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            int numDevs = 0;
            switch (cboNetworkAdapter.SelectedIndex)
            {
                case 0:
                    numDevs = 4;
                    break;
                case 1:
                    numDevs = 1;
                    break;
                case 2:
                    numDevs = 10;
                    break;
            }
            populateImages(numDevs);
        }

        void bkgndWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prgBarConnect.Value = e.ProgressPercentage;
        }

        void bkgndWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            foreach (KeyValuePair<String, int> entry in dictionary)
            {
                ListViewItem lstViewDevImage = new ListViewItem(entry.Key, entry.Value);
                lstvwDevIds.Items.Add(lstViewDevImage);
            }

            if (lstvwDevIds.SelectedItems.Count > 0)
                Console.WriteLine(String.Format("Device id: {0}", lstvwDevIds.Items.IndexOf(lstvwDevIds.SelectedItems[0])));

            lstvwDevIds.LargeImageList = deviceImageList;
        }

        private void populateImages(int numDevs)
        {
            for (int i = 1; i <= numDevs; i++)
            {
                System.Threading.Thread.Sleep(100);
                int percents = (i * 100) / numDevs;

                String lstVwItemDesc = String.Format("Dev {0}", i - 1);
                dictionary.Add(lstVwItemDesc, deviceImageList.Images.Count - 1);
                bkgndWorker.ReportProgress(percents, i);
            }
        }
    }
}

表格加载成功

Don't call Dispose on a BackGroundWorker that you want to have running. Do this instead:

// if we have an instance of a backgroundworker ...
// Cancel and Dispose that one
if (bkgndWorker !=null) 
{
    // in case you want to end the DoWork nicely
    bkgndWorker.CancelAsync(); 
    bkgndWorker.Dispose();
}

// start again
bkgndWorker = new BackgroundWorker();

bkgndWorker.DoWork += new DoWorkEventHandler(bkgndWorker_DoWork);
bkgndWorker.ProgressChanged += new ProgressChangedEventHandler(bkgndWorker_ProgressChanged);
bkgndWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bkgndWorker_RunWorkerCompleted);
bkgndWorker.WorkerReportsProgress = true;
bkgndWorker.RunWorkerAsync();
// removed the call to Dispose

You might want to implement Dispose on your form as well to do the same cleanup of your BackgroundWorker instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM