【问题标题】:Button hangs with infinite loop [duplicate]按钮挂起无限循环[重复]
【发布时间】:2016-08-20 01:02:55
【问题描述】:

如果我启动我的 C# Windows 窗体应用程序,按钮会挂起,因为它是无限循环。我想通过全局变量查看button2点击进入button1无限循环的变量值变化

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;

namespace XX_5
{
    public partial class Form1 : Form
    {
        private int g;

        public Form1()
        {
            InitializeComponent();
        }   
        private void button1_Click(object sender, EventArgs e)
        {           
            int i = 0;

            for (;;)
            {   
                textBox1.AppendText("ID: [" + i++ + "] Variable value: [" + g + "]\n");    
            }
        }    
        private void button2_Click(object sender, EventArgs e)
        {
            g = 1;
        }
    }
}

【问题讨论】:

  • @Grant Winney 你好,你能告诉我一些例子如何做同样但正确的方式,GUI中的无限循环和从button2到button1内处理的值我只是想在什么时候改变它button2 被按下
  • 这个问题太宽泛了,特别是考虑到 Stack Overflow 上已经存在多少关于不阻塞 UI 线程的基本概念的问答。只有一个线程处理 UI 的绘制。如果您不让该线程执行任何其他操作,因为您陷入了无限循环,那么 绘制 UI 将不会发生。有关如何处理此问题的一些建议,请参阅标记的副本。
  • 对于 .NET 4.5,我建议 Task.Run() 开始操作,并建议 Progress<T> 将任何相关的进度报告提供回主线程。或者,您可以在循环中使用async/await,其中await 对循环的每次迭代执行Task.Run() 操作。
  • 最简单的方法是将Application.DoEvents(); 放入循环中。 一般而言Application.DoEvents() 被认为是一种 hack。使用Taskasync/await 通常会带来更易于维护的设计。

标签: c# winforms global-variables infinite-loop cycle


【解决方案1】:

如果您在按钮单击事件处理程序中保持无限循环,您的应用程序肯定会挂起,因为 Windows 无法再获取/调度/处理消息。

你可以像下面这样修复:

private void button1_Click(object sender, EventArgs e)
    {           
        int i = 0;
        textBox1.AppendText("ID: [" + i++ + "] Variable value: [" + g + "]\n");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        // int g = 1; // here you declare a local variable
        g = 1;  // use the member variable instead
    }

【讨论】:

  • “i”也应该是会员。
  • 是的,现在变量可以工作,但是如何在我的无限循环中查看从 button2 点击获得的变量变化,如何使按钮工作
  • 原代码明明有循环,但是这个答案没有循环,这个建议在这种情况下完全不合适。
【解决方案2】:

查看 Timer 控件(在工具箱的“组件”选项卡下)。你可以把你的代码(没有for循环)放在那里,它会每x毫秒运行一次,好处是它不会挂起。执行此操作时,您需要在表单级别定义 i 变量。然后,您的计时器可以访问此“全局变量”。

这样的……

public partial class Form1 : Form
{

    private int i = 0;
    private int g = 0;
    public Form1()
    {
        InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        g = 1;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        textBox1.AppendText("ID: [" + i++ + "] Variable value: [" + g + "]\n");
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        timer1.Enabled = true;
    }
}

【讨论】:

  • 不太明白计时器在这种情况下是如何工作的,你能给我举个例子吗,对我来说很重要的是让这个无限循环进入内部并查看从 button2 click 获得的变量变化
  • 原始代码中没有任何内容涉及操作之间的周期性延迟,因此在这种情况下使用计时器是完全不合适的建议。
  • 如果无限循环不让 CPU 使用,那么计时器是 C# 学习者解决问题的最简单方法。重点不是定期延迟 - 重点是让步。问题作者显然是想通过尝试小任务来学习 C# - 在这个阶段学习线程是不合适的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-04
  • 2020-06-06
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
相关资源
最近更新 更多