在每个FOR循环中在屏幕上显示结果?

时间:2011-09-14 00:03:44

标签: c# loops for-loop iteration

我正在编写一架飞机的随机座椅发电机,我正在使用FOR循环。问题是,占用的座位只在一切都完成后显示。我希望它做的是在每次迭代中,显示所选的随机座位。如何做到这一点?

这是我正在使用的代码。这架飞机有118个座位,每个人都有一个名为“img_Seat_X”的图片箱。我知道有一个更好的方法,但我可以在一个小时内思考。提前致谢!

private void btn_WeightBalance_Populate_Click(object sender, EventArgs e)
{
                int passengers = Convert.ToInt32(txt_WeightBalance_Passengers.Text);
                List<int> seats = new List<int> { }; numberofSeats = 119;

                if (rdb_WeightBalance_190.Checked == true)
                    numberofSeats = 107;

                for (int x = 0; x < Passengers; x++)
                {
                    int randomNumber = RandomNumber(1, numberofSeats);

                    if (seats.Contains(randomNumber))
                        x--;

                    else
                    {

                        seats.Add(randomNumber);

                        Control[] seat = this.panWeightBalance.Controls.Find("img_Seat_" + randomNumber, true);
                        seat[0].Visible = true;
                        seat[0].Refresh();
                    }
                }
}

想出来!每次迭代都有一个简单的Refresh()来完成工作!我还用if语句替换了while循环。

5 个答案:

答案 0 :(得分:2)

首先,必读:The Windows Message Loop

@rice指出我明显的错误,抱歉让你走错了路,谢谢米。

无论如何,您可以在单独的线程中执行工作,并使用BackgroundWorker类将更新发布到UI trhead。这是一个简单的例子,它响应按钮点击更新表单上的标签100次:

public partial class Form1 : Form
{
    BackgroundWorker _worker;
    public Form1()
    {
        InitializeComponent();
        _worker = new BackgroundWorker();
        _worker.WorkerReportsProgress = true;
        _worker.DoWork += _worker_DoWork;
        _worker.ProgressChanged += _worker_ProgressChanged;
    }

    private void _worker_ProgressChanged( object sender, ProgressChangedEventArgs e )
    {
        label1.Text = e.UserState.ToString();
    }

    private void _worker_DoWork( object sender, DoWorkEventArgs e )
    {
        for( int i = 0; i < 100; ++i )
        {
            _worker.ReportProgress( i, i );
            // allow some time between each update,
            // for demonstration purposes only.
            System.Threading.Thread.Sleep( 15 );
        }
    }   

    private void button1_Click( object sender, EventArgs e )
    {
        _worker.RunWorkerAsync();
    }
}

答案 1 :(得分:1)

基本上,您需要生成后台线程来进行处理,然后每次使用BeginInvoke更新用户界面元素。您需要在此解决方案中解决一些问题。用户现在可以继续单击该按钮,它将生成其他后台线程。最常见的机制是弹出一个进度对话框(我讨厌模态对话框,所以不要这样做)或者阻止用户通过禁用按钮来完成两次操作直到工作完成。

    private void btn_WeightBalance_Populate_Click(object sender, EventArgs e)
    {
        int passengers = Convert.ToInt32(txt_WeightBalance_Passengers.Text);

        List<int> seats = new List<int> { }; numberofSeats = 119;

        if (rdb_WeightBalance_190.Checked == true)
            numberofSeats = 107;

        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += delegate
        {
            for (int x = 0; x < passengers; x++)
            {
                int randomNumber = RandomNumber(1, numberofSeats);
                while (seats.Contains(randomNumber))
                {
                    randomNumber = RandomNumber(1, numberofSeats);
                }
                seats.Add(randomNumber);

                UpdateSeat(randomNumber);
            }
        };
        worker.RunWorkerAsync();
    }

    /// <summary>
    /// Update a seat control in the correct UI thread. If this
    /// method is invoked in a thread besides the UI thread it will use
    /// BeginInvoke to put it on the UI thread queue.
    /// </summary>
    /// <param name="seatNumber"></param>
    private void UpdateSeat (int seatNumber)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke((Action)(() => UpdateSeat(seatNumber)));
        }
        else
        {
            Control[] seat = this.Controls.Find("img_Seat_" + seatNumber, true);
            seat[0].Visible = true;
        }
    }

还有其他问题需要解决。例如,在调用FindControl并且不处理txt_WeightBalance_Passengers中格式错误的数字文本时,控件将始终存在。

以'可爱'回答更新

    private void btn_WeightBalance_Populate_Click(object sender, EventArgs e)
    {
        var passengers = Convert.ToInt32(txt_WeightBalance_Passengers.Text);
        numberofSeats = rdb_WeightBalance_190.Checked ? 107 : 119;
        var worker = new BackgroundWorker();
        worker.DoWork += delegate
        {
            var random = new Random();
            foreach (var seatNumber in Enumerable.Range(1, Int32.MaxValue).Select(r => random.Next(numberofSeats)).Distinct())
            {
                var randomSeat = seatNumber;
                BeginInvoke((Action)(() =>
                {
                    var seat = this.Controls.Find("img_Seat_" + randomSeat, true);
                    seat[0].Visible = true;
                }));                    
                if (--passengers <= 0) break;
            }
        };
        worker.RunWorkerAsync();
    }

答案 2 :(得分:0)

不是获取一个随机数,检查它是否被采用然后分配它,我会取一个列表1 thru numberOfSeats并将其随机播放并开始以此随机洗牌顺序分配席位。这样可以避免恶性while (Seats.Contains(randomNumber)){...}循环。

答案 3 :(得分:0)

您所编写的代码仅从最多119个席位中选择随机席位。即使您使用的是旧硬件,也应该令人眼花缭乱才能运行,所以我不明白为什么您需要在分配时显示每个座位。在我看来,你应该拆分代码。计算座位分配,然后以您喜欢的方式显示它们。

以下是随机选择座位的代码:

var passengers = Convert.ToInt32(txt_WeightBalance_Passengers.Text);
var numberofSeats = rdb_WeightBalance_190.Checked ? 107 : 119;

// Creates an array from 0 .. numberofSeats - 1
var seats = Enumerable.Range(0, numberofSeats).ToArray();

//Shuffle the first "passengers" elements of the array
for (var i = 0; i < passengers; i++)
{
    var j = RandomNumber(0, numberofSeats);
    var x = seats[i];
    seats[i] = seats[j];
    seats[j] = x;
}

//Find the first "passengers" count of seat controls
var controls = (
        from i in seats.Take(passengers)
        let c = this.Controls.Find("img_Seat_" + i, true).FirstOrDefault()
        where c != null
        select c
    ).ToArray();

现在将座椅控制设置为可见,只需执行以下操作:

foreach (var c in controls)
{
    c.Visible = true;
}

如果您有特殊需要在后台运行此功能并更新UI,则可以执行以下操作:

var t = new System.Threading.Thread(new ThreadStart(() =>
{
    foreach (var c in controls)
    {
        this.Invoke(new Action(() => c.Visible = true));
        // Thread.Sleep(100); // Slow it down if you wish...
    }
}));
t.Start();

这对你有用吗?

答案 4 :(得分:-1)

  事情是,占用的座位只在一切都完成时显示。

预计在for循环中查看while循环:

while (Seats.Contains(randomNumber))
{
    randomNumber = RandomNumber(1, numberofSeats);
}
Seats.Add(randomNumber); 

您可能忘记在while循环中添加“Add”方法。还要检查退出条件 - 我想你想在Contains返回true时退出while循环。