2

收到跨线程异常错误后,我在MSDN上查找。

我尝试在那里实现一些代码,但无法让回调工作。

addItemCallback d = new addItemCallback(addItem);

这位于下面的 addItem() 方法中。

我正在尝试将项目列表添加到列表框中,最终每次找到一个值时都会更新表单,而不是在后台程序完成工作后添加所有项目。

private void startWork()
{        
    progressBar1.Value = 0;

    progressBar1.Maximum = 901242;

    backgroundWorker1.RunWorkerAsync();    
}

private void getList()
{
    if (pathFound)
    {
        for (int i = 0; i < numberOfPaths; i++)
        {
            Microsoft.Win32.RegistryKey mainPath = secondaryPath.OpenSubKey("application " + Convert.ToString(i));

            if (mainPath != null)
            {
                    this.addItem((string)mainPath.GetValue("Name"));
            }

            backgroundWorker1.ReportProgress(i);
        }
    }

    pathListBox.Sorted = true;
}

private void addItem(string item)
{
    if (this.pathListBox.InvokeRequired)
    {

        //addItemCallback d = new addItemCallback(addItem); 

        //not sure what this callBack is, can't get it to work, Callback isnt found.

        this.Invoke(d, new object[] { item });
    }

    else 
    {
        this.pathListBox.Items.Add(item);
    }
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    getList();
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    this.progressBar1.Visible = false;
}

工作至今

代码 1. 当我使用 background_doWork 并从中调用一个方法时,进度条挂在随机位置并停止响应,在关闭表单时我得到一个对象异常,因为我在它仍在尝试工作时关闭了表单。

代码 2。当我将所有代码放在 background_doWork 中而不是从中调用方法时,进度条有时会工作,每秒或每 3 次尝试运行它完成的程序。

什么会导致这种情况?

-----代码 1------------

    public Form1()
    {
        InitializeComponent();

        start();
    }

    int number = 900000;

    public void start()
    {
        progressBar1.Value = 0;

        progressBar1.Maximum = number;

        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        getList();
    }

    private void getList()
    {
        Microsoft.Win32.RegistryKey mainPath = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node");

        for (int i = 0; i < number; i++)
        {
            Microsoft.Win32.RegistryKey mainPath = secondaryPath.OpenSubKey("application " + Convert.ToString(i));

            if (mainPath != null)
            {
                this.addItem((string)mainPath.GetValue("Name"));
            }

            backgroundWorker1.ReportProgress(i);
        }
    }

    private void addItem(string item)
    {
        try
        {

            if (this.listBox1.InvokeRequired)
            {
                this.Invoke(new Action<string>(addItem), item);
            }

            else
            {
                this.listBox1.Items.Add(item);
            }
        }

        catch
        {
            MessageBox.Show("Error - Closed Object before it finished working.");
        }

        //this.steamGamesListBox.Sorted = true;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.progressBar1.Visible = false;
    }

------代码2 --------

    public Form1()
    {
        InitializeComponent();

        start();
    }

    int number = 900000;

    public void start()
    {
        progressBar1.Value = 0;

        progressBar1.Maximum = number;

        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Microsoft.Win32.RegistryKey steamApps64 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");

        for (int i = 0; i < number; i++)
        {
            Microsoft.Win32.RegistryKey steamApps = steamApps64.OpenSubKey("Steam App " + Convert.ToString(i));

            if (steamApps != null)
            {
                this.addItem((string)steamApps.GetValue("DisplayName"));
            }

            backgroundWorker1.ReportProgress(i);
        }
    }

    private void addItem(string item)
    {
        try
        {

            if (this.listBox1.InvokeRequired)
            {
                this.Invoke(new Action<string>(addItem), item);
            }

            else
            {
                this.listBox1.Items.Add(item);
            }
        }

        catch
        {
            MessageBox.Show("Error - Closed Object before it finished working.");
        }

        //this.steamGamesListBox.Sorted = true;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.progressBar1.Visible = false;
    }
4

2 回答 2

3

您要么需要定义自定义委托类型(您的addItemCallback),要么只需使用通用Action委托:

private void addItem(string item)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new Action<string>(addItem), item);
        return;
    }

    this.pathListBox.Items.Add(item);
}

这通常是最简单的方法,因为您不需要引入额外的委托类型。

请注意,object[]参数是使用params关键字定义的,因此您不需要实例化新object数组,而只需将参数传递给方法。

于 2012-02-24T10:18:19.660 回答
0

添加delegate void addItemCallback(string item);

于 2012-02-24T10:19:27.650 回答