2

下面的代码给了我下面的错误。我想我需要 "InvokeRequired" 。但我不明白我该如何使用?

错误:跨线程操作无效:控件“statusBar1”从创建它的线程以外的线程访问。

编码 :

 public void CalculateGeneration(int nPopulation, int nGeneration)

    {

        int _previousFitness = 0;
        Population TestPopulation = new Population();

        for (int i = 0; i < nGeneration; i++)
        {
            if (_threadFlag)
                break;
            TestPopulation.NextGeneration();
            Genome g = TestPopulation.GetHighestScoreGenome();

            if (i % 100 == 0)
            {
                Console.WriteLine("Generation #{0}", i);
                if (  ToPercent(g.CurrentFitness) != _previousFitness)
                {
                    Console.WriteLine(g.ToString());
                    _gene = g;

                    statusBar1.Text = String.Format("Current Fitness = {0}",                g.CurrentFitness.ToString("0.00"));
                    this.Text = String.Format("Sudoko Grid - Generation {0}", i);
                    Invalidate();
                    _previousFitness = ToPercent(g.CurrentFitness);
                }

                if (g.CurrentFitness > .9999)
                {
                    Console.WriteLine("Final Solution at Generation {0}", i);
                    statusBar1.Text = "Finished";
                    Console.WriteLine(g.ToString());
                    break;
                }
            }


        } 


    }
4

1 回答 1

2

最简单的可重用性是添加一个辅助函数,例如:

    void setstatus(string txt)
    {
        Action set = () => statusBar1.Text = txt; 
        statusBar1.Invoke(set);
    }

或者首先使用 invokerequired 检查:

    delegate void settextdelegate(string txt);
    void setstatus(string txt)
    {
        if (statusBar1.InvokeRequired)
            statusBar1.Invoke(new settextdelegate(setstatus), txt);
        else
            statusBar1.Text = txt;             
    }

无论哪种方式,状态都可以设置为

 setstatus("Finished");

为了完整起见,我应该补充一点,最好将您的计算逻辑与您的表单分开,并从您的计算功能中提出一个可以由表单处理的状态,但这可能完全超出了这里的范围。

于 2012-06-06T09:05:13.240 回答