为什么{}while()循环不能在button_Click()方法体中工作?

本文关键字:方法 Click 工作 while 循环 为什么 不能 button | 更新日期: 2023-09-27 18:13:04

这段代码在控制台应用程序中可以正常工作,但是当我在windows窗体应用程序中使用它时,它不能正常工作。它从不停止,也不产生任何输出。

我在像这样的控制台应用程序中使用它,它工作:

 static void Main(string[] args)
    {
     Console.WriteLine("Enter your boolean query");
        do{
            string query = Console.ReadLine();
            List<int> lst = ProcessQuery(query);
            count = 0;
            if (lst!=null)
            {
                foreach (int a in lst)
                {
                    if (a == 1)
                    {
                        Console.WriteLine(documentContentList[count]);
                    }
                    count++;
                }
            }
            else
            {
                Console.WriteLine("No search result found");
            }
        }  while(1==1);
    }

我尝试在windows窗体应用程序中的button_click方法上使用上述代码,但它不起作用。我认为while(1==1)有问题,有类似的吗?

下面是我为按钮编写的方法:

 private void button6_Click(object sender, EventArgs e)
    {
        if (t == null)
        {
            MessageBox.Show("Click on LoadFile Button,Please.");
            return;
        }
        if (textBox4.Text == "")
        {
            MessageBox.Show("Enter your Boolean Query");
            return;
        }
        listBox1.Items.Clear();
        DateTime dt = DateTime.Now;
        do{
            List<int> lst = t.ProcessQuery(textBox4.Text);
            count = 0;
            if (lst != null)
            {
                foreach (int a in lst)
                {
                    listBox1.Items.Add(t.documentContentList[count]);
                }
                count++;
            }
            else
            {
                listBox1.Items.Add("No Search Result Found");
            }
            label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s";
        } while (1==1);
    }

为什么{}while()循环不能在button_Click()方法体中工作?

我相信从button_click事件处理程序中删除do while循环将为您完成这项工作。

private void button6_Click(object sender, EventArgs e)
    {
        if (t == null)
        {
            MessageBox.Show("Click on LoadFile Button,Please.");
            return;
        }
        if (textBox4.Text == "")
        {
            MessageBox.Show("Enter your Boolean Query");
            return;
        }
        listBox1.Items.Clear();
        DateTime dt = DateTime.Now;
        //do{
            List<int> lst = t.ProcessQuery(textBox4.Text);
            count = 0;
            if (lst != null)
            {
                foreach (int a in lst)
                {
                    listBox1.Items.Add(t.documentContentList[count]);
                }
                count++;
            }
            else
            {
                listBox1.Items.Add("No Search Result Found");
            }
            label1.Text = "Search = " + listBox1.Items.Count + " items, " + DateTime.Now.Subtract(dt).TotalSeconds + " s";
       // } while (1==1);
    }

控制台应用程序在同步等待使用

获取用户输入时暂停执行。
string query = Console.ReadLine();

,当它获得输入时,它进行必要的计算并打印要打印的内容,并再次在同一行等待下一个输入。

winform应用程序不这样工作,它已经有一个事件循环来处理UI活动(按键等)

简而言之,在处理程序方法中不需要循环。

在Windows窗体或WPF中,UI仅由单个线程管理。所以如果你在代码中有一个无限循环UI从它的线程调用,它将永远阻塞,并且无法继续更新UI。这就是为什么你不会看到任何对话框出现。

相反,你应该在它自己的线程中运行类似这样的代码,或者在BackgroundWorker对象的构造中更容易运行(然后使用DoWork和ProgressChanged事件)。

我很清楚;在控制台应用程序中,您有一个控制台。在循环内的ReadLine使循环停止,直到用户输入一个值并点击Return。在表单应用程序中,不需要do while循环。用户在textBox4中输入一个值,然后单击一个按钮来处理请求。

在控制台应用程序中,Main是应用程序的入口点。所有的程序都有这个函数,当你启动一个可执行文件时,操作系统会调用它。

一旦调用,它将像任何其他函数一样执行(从上到下),如果Main返回一个值,它将返回给操作系统,操作系统终止程序。

为了防止程序在一次运行后退出,通常的做法是使用while循环来确保没有到达main函数的末尾(并执行return)。

Console.ReadLine是一个阻塞函数——这意味着它不会让下一行代码执行,直到它完成它所做的任何事情(在这里,从用户那里读取输入)。

所以控制台应用程序逐行运行,直到得到输入。然后求值,输出一个字符串并永远重复。

现在,在WinForms应用程序中,事情的管理有点不同。UI(按钮,表单,文本框等)是由主线程处理的,这意味着你需要给它更新的时间。通过在你的按钮点击函数中设置一个无限循环,你永远不会将控制权返回给主线程,UI将被锁定。

如果你只想让函数运行多次,删除while循环,代码将在每次点击按钮时运行。Winforms将为您处理。

如果它仍然锁定UI,则代码阻塞时间过长(在按钮事件中)。

如果是这样,您必须异步地(一点一点地)执行密集的工作,或者将工作卸载到另一个线程。考虑使用backgroundWorkers来确保UI不会冻结,并删除无限循环。

  1. 你在两个例子中都有无限循环条件-所以你的程序永远无法优雅地退出循环,即使在你的控制台应用程序中,你可能通过点击它的'x'关闭控制台表单来退出,这是错误的。

  2. 程序应该有一个逻辑实现,允许用户优雅地退出程序。
  3. 你的第二个例子没有像你期望的那样工作的原因是因为它从不允许刷新你的用户界面。设置无限循环是一种不好的做法,但是为了向你证明它实际上没有卡住或冻结,它只是无法刷新用户界面,在循环中添加另一个命令,如下所示:

<>之前:listBox1.Items。添加("未找到搜索结果");}label1。Text = "Search = " + listBox1.Items。Count +"items"+ DateTime.Now.Subtract(dt)。总秒数+ " s";Application.DoEvents ();//添加这一行} while (1==1);之前

Application.DoEvents();暂停循环的执行,并允许图形用户界面线程更新窗口。

但是正如我之前所说的,这不是开发应用程序的正确方法,更好的方法是简单地删除该循环,如下所示:

<>之前private void button6_Click(对象发送者,EventArgs e){If (t == null){对话框。显示("请点击加载文件按钮");返回;}如果(textBox4。Text == "){对话框。Show("Enter your Boolean Query");返回;}listBox1.Items.Clear ();DateTime dt = DateTime. now;列表lst = t.ProcessQuery(textBox4.Text);Count = 0;If (lst != null){Foreach (int a in list){listBox1.Items.Add (t.documentContentList[数]);}数+ +;}其他的{listBox1.Items。添加("未找到搜索结果");}label1。Text = "Search = " + listBox1.Items。Count +"items"+ DateTime.Now.Subtract(dt)。总秒数+ " s";}之前

现在,每次单击按钮时,它都会调用事件处理程序,当事件处理程序退出例程时,用户界面将自动更新。因为你的窗体是从System.Windows.Form类派生出来的,所以在用户点击'x'之前保持windows消息泵运行的指令已经在父类中为你实现了,也就是你的窗体是从System.Windows.Form类派生出来的。

当然,在控制台应用程序中不会出现这种情况。

在您的控制台示例中,Consol.ReadLine()调用阻塞了UI &等待输入。通过使用无限while循环,您可以有效地允许用户输入任意数量的查询。然而,在基于Forms/WPF的应用程序中,无限循环实际上是一个糟糕的想法,加上应用程序将一直保持直到关闭,而不是在完成工作后立即关闭(这就是为什么您在控制台应用程序中使用无限循环)。

这是因为基于表单的应用程序利用专用线程来更新UI。通过阻塞这个线程,您还可以防止发生任何其他UI更新,从而冻结您的应用程序。根据你想做的,button6_Click事件方法应该卸载这个工作到一个BackgroundWorker(文档),它允许工作在另一个线程上执行,然后封送更新到UI线程。