2

クロススレッド例外エラーを受け取った後、MSDNで調べました。

そこでいくつかのコードを実装しようとしましたが、コールバックを機能させることができません。

addItemCallback d = new addItemCallback(addItem);

これは、以下のaddItem()メソッドにあります。

アイテムのリストをリストボックスに追加しようとしています。最終的には、バックグラウンダーが作業を終了した後にすべてのアイテムを追加するのではなく、1つの値が見つかるたびにフォームを更新します。

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に配置すると、プログレスバーが機能することがあります。これは、終了するプログラムの実行を1秒ごとまたは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

カスタム デリゲート タイプ ( your 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 に答える