0

我正在为朋友的生日申请,应该会弹出一个带有不断变化的赞美的窗口。但是,窗口会冻结,并且标签不会更改。我用谷歌搜索了它,并阅读了一些关于使用 Backgroundworker 的内容,以便将 GUI 线程与不断变化的进程分开。还是不行。

这是我的代码:

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

namespace ProjectL
{
    public partial class Form1 : Form
    {
        private MessageHandler theHandler = new MessageHandler();
        private BackgroundWorker theBackgroundWorker = new BackgroundWorker();
        public Form1()
        {
            InitializeComponent();
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            StartButton.Visible = false;
            theBackgroundWorker.DoWork += new DoWorkEventHandler(theBackgroundWorker_doYourWork);
            //theBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(theBackgroundWorker_doYourWork);
            theBackgroundWorker.RunWorkerAsync();        

            theHandler.RunMessage(hBDLabel, youAreLabel, mainLabel, this);
        }

        void theBackgroundWorker_doYourWork(object sender, DoWorkEventArgs e)
        {
            theHandler.RunMessage(hBDLabel, youAreLabel, mainLabel, this);
        }
    }
}

这是应该在后台发生的事情,使用我命名为 MessageHandler 的类:

class MessageHandler
{
    public List<String> GenerateComplimentTexts()
    {
        List<String> stringList = new List<String>();
        //Adding a bunch of compliments into a List<String>

        return stringList;
    }

    public void RunMessage(Label hBDLabel, Label youAreLabel, Label mainLabel, Form1 form)
    {
        List<String> stringList = GenerateComplimentTexts();
        Thread.Sleep(2000);
        form.Text = "Happy Birthday Goose!!!";
        hBDLabel.Text = "Happy Birthday Goose!";
        Thread.Sleep(3000);
        youAreLabel.Text = "You are...";
        Thread.Sleep(2000);
        foreach (String e in stringList)
        {
            mainLabel.Text = e;
            //form.Test = e

            Thread.Sleep(1000);
        }
        Thread.Sleep(3000);
        mainLabel.Text = "";
        youAreLabel.Text = FinalMessage;
    }

    private String _finalMessage = "FINAL MESSAGE";
    public String FinalMessage {get {return _finalMessage;}}
}

尽管如此,我的窗户上没有任何变化。如果我选择取消注释 form.Text = e; ,除了表单本身顶部栏中的文本外,一切都几乎被冻结了。

有什么建议吗?

4

4 回答 4

1

您可以使用Timers而不是 BackgroundWorker来实现它。

它可能看起来像这样:

主窗体:

public partial class Form1 : Form
{
    private Timer timer;
    private MessageHandler theHandler = new MessageHandler();

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        timer = new Timer();
        timer.Interval = 1000;
        timer.Tick += TimerOnTick;
        // Initialize the other labels with static text here
    }

    private void TimerOnTick(object sender, EventArgs eventArgs)
    {
        theHandler.ShowNext(label1);
    }

    private void StartButton_Click(object sender, EventArgs e)
    {
        timer.Start();
    }
}

和 MessageHandler 类:

public class MessageHandler
{
    private List<String> compliments = new List<string>();
    private int index = 0;

    public MessageHandler()
    {
        GenerateComplimentTexts();
    }

    private void GenerateComplimentTexts()
    {
        List<String> stringList = new List<String>();
        //Adding a bunch of compliments into a List<String>
        compliments = stringList;
    }

    public void ShowNext(Label label)
    {
        label.Text = compliments.ElementAt(index);
        index = (index >= compliments.Count - 1) ? 0 : index + 1;
    }
}
于 2013-05-14T18:51:47.417 回答
0

要更新 UI,请使用后台工作程序的 ReportProgress 方法。ReportProgress 引发 ProgressChanged 事件,您可以从那里更新您的 UI。请务必将 backgroundworker 的 WorkerReportsProgress 属性设置为 true。

于 2013-05-14T18:46:25.867 回答
0

尝试一下:1.) 将计时器复制到表单 2.) 将以下代码复制到 timer1_tick-Event 中。

private int _counter;
private int _currentIndex;

  private void timer1_Tick(object sender, EventArgs e)
    {
            switch (_counter)
            {
                case 1:
                   form.Text = "Happy Birthday Goose!!!";
                   hBDLabel.Text = "Happy Birthday Goose!";
                   break;

                case 2:
                    timer1.Interval = 3000;
                    break;
                case 3:
                    youAreLabel.Text = "You are...";
                    break;
                case 4:
                    if (stringlist.count = (_currentIndex -1))
                    {
                        timer1.Enabled = false;

                    }else {
                         mainLabel.Text = e;
                         timer1.Interval = 1000;
                       return;
                    }
                     break;
                    }

           _counter ++;

}

不是最优雅的方式,但它应该工作。

于 2013-05-14T19:03:34.293 回答
0

试试这个代码:

private void StartButton_Click(object sender, EventArgs e)
    {
        StartButton.Visible = false;
        theBackgroundWorker.DoWork += new DoWorkEventHandler(theBackgroundWorker_doYourWork);      
        theBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(theBackgroundWorker_ProgressChanged);
        theBackgroundWorker.RunWorkerAsync();        

    }

    void theBackgroundWorker_doYourWork(object sender, DoWorkEventArgs e)
    {
         var w = sender as BackgroundWorker;

         List<String> stringList = GenerateComplimentTexts();
         Thread.Sleep(2000);
         w.ReportProgress(0, "Happy Birthday Goose!!!");
         w.ReportProgress(1, "Happy Birthday Goose!");      
         Thread.Sleep(3000);
         w.ReportProgress(2, "You are...");    
         Thread.Sleep(2000);
         foreach (String e in stringList)
         {
             w.ReportProgress(3, e);                
             Thread.Sleep(1000);
         }
         Thread.Sleep(3000);
         w.ReportProgress(3, "");  
         w.ReportProgress(2, FinalMessage);
    }

    void theBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

        var msg = e.UserState.ToString();
        switch (e.ProgressPercentage)
        { 
            case 0:
                 form.Text = msg;
                 break;
            case 1:
                hBDLabel.Text=msg;
                break;
            case 2:
                youAreLabel.Text =msg;
                break;
            case 3:
                mainLabel.Text=msg;
                break;

        }        
    }
于 2013-05-14T19:04:31.537 回答