如何从BackgroundWorker在Windows窗体中设置标签文本

时间:2016-10-05 10:29:08

标签: c# winforms

所以我目前正在为使用Windows Forms和C#的游戏编写一个Level Generator。我有一个BackgroundWorker正在执行所有生成,因此UI线程不会被阻止,并且可以根据需要自行更新。我目前使用BackgroundWorkers ReportProgress()函数更新进度条,但id也希望能够根据生成器所处的位置更新标签,即"初始化级别2",&#34 ;将对象放置在3级和#34;等。

我尝试从backgroundWorker中调用updateProgress()函数(我将它传递给Generator构造函数),但是它没有工作,因为我遇到了交叉线程错误。

 public partial class mainForm : Form
    {
        LevelGen Generator;
        List<Level> levelSet;

        public mainForm()
        {
            InitializeComponent();;
            Generator = new LevelGen(this, backgroundWorker, timer);
        }



        private void button_GenLevels_Click(object sender, EventArgs e)
        {             
            if (!backgroundWorker.IsBusy)
            {
                progressBar.Value = 0;

                backgroundWorker.RunWorkerAsync();
            }
            else
            {
                backgroundWorker.CancelAsync();
            }
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            levelSet = Generator.startGeneration();
        }

        public void updateProgress(int percentage, string currentWork)
        {
            label_processInfo.Text = percentage + " - " + currentWork;
            backgroundWorker.ReportProgress(percentage);
        }

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

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ListLevels(levelSet);
        }

    }

它会在发电机内被调用:

public Level generateLevel(int noOfLevels, int noOfBoxes, int roomHeight, int roomWidth, int difficulty, int levelNum, int totalLevels)
        {
            bool generationSuccessful = false;
            Level newLevel = new Level();
            float percentage;
            int indProcesses = 2;
            int totalProcesses = totalLevels * (indProcesses + 1);

            while (!generationSuccessful)
            {
                newLevel = new Level();

                calculateProperties(ref noOfBoxes, ref difficulty, ref roomHeight, ref roomWidth);

                percentage = (((levelNum * indProcesses)) * 100) / totalProcesses;
                form.updateProgress((int)percentage, "Init Level " + levelNum);

                initLevel(ref newLevel, roomHeight, roomWidth);

                percentage = (((levelNum * indProcesses) + 1) * 100) / totalProcesses;
                form.updateProgress((int)percentage, "Placing Patterns in Level " + levelNum);

                placePatterns(ref newLevel, roomHeight, roomWidth);

                generationSuccessful = true;
            }

            percentage = (((levelNum * indProcesses) + 2) * 100) / totalProcesses;
            form.updateProgress((int)percentage, "Level " + levelNum + " Generated");

            return newLevel;
        }

如何告知Windows表单标签在Generator中更新?

2 个答案:

答案 0 :(得分:1)

基于我刚刚发表的评论。

 public void updateProgress(int percentage, string currentWork)
    {
        label_processInfo.Text = percentage + " - " + currentWork;
        backgroundWorker.ReportProgress(percentage,"New Label Value");
    }
 private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
        string newLabelValue = (String)e.UserState;
    }

用户状态也是一个对象,因此您可以发送任何内容。

答案 1 :(得分:0)

您还可以使用委托并检查.InvokeRequired是否以线程安全的方式更新UI元素:

delegate void SetTextCallback(string text);
private void SetDebugText(string RxString)
    {
        if (this.btnDebug.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetDebugText);
            this.Invoke(d, new object[] { RxString });

        }
        else
        {
            this.btnDebug.Text = RxString;
        }
    }