0

此代码在控制台应用程序中正常工作,但是当我在 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);

    }

我尝试button_click在 Windows 窗体应用程序中的方法上使用上述代码,但它不起作用。我认为有问题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);

    }
4

6 回答 6

3

我相信从 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 活动(KeyPressed 等)

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

于 2013-05-09T14:46:17.153 回答
0

在您的控制台示例中,Consol.ReadLine()调用会阻止 UI 并等待输入。通过使用无限 while 循环,您可以有效地允许用户输入任意数量的查询。但是,在基于 Forms/WPF 的应用程序中,无限循环实际上是一个糟糕的主意,而且应用程序将一直运行到关闭,而不是在您的工作完成后立即关闭(这就是您在控制台应用程序中使用无限循环的原因) .

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

于 2013-05-09T14:45:39.713 回答
0

在控制台应用程序中,Main是应用程序的入口点。所有程序都具有此功能,并且在您启动可执行文件时由操作系统调用。

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

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

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

因此,您的控制台应用程序会逐行运行,直到获得输入。然后它对此进行评估,输出一个字符串并永远重复。

现在,在 WinForms 应用程序中,事情的管理方式略有不同。UI(按钮、表单、文本框等)由主线程处理,这意味着您需要给它时间来更新。通过在您的按钮单击功能中设置无限循环,您永远不会将控制权返回给主线程并且 UI 会锁定。

如果您只是希望函数多次运行,请删除while循环,每次单击按钮时代码都会运行。Winforms 将为您处理。

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

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

于 2013-05-09T14:57:59.203 回答
0

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

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

于 2013-05-09T14:40:56.827 回答
0
  1. 您在两个示例中都有无限循环条件 - 因此您的程序永远无法正常退出循环,即使在您的控制台应用程序中,您可能通过单击它的“x”关闭控制台表单来退出,这是错误的.. 程序应该实现了一个逻辑以允许用户优雅地退出它。

  2. 您的第二个示例无法按预期工作的原因是因为它永远不允许刷新您的用户界面。放置无限循环是一种不好的做法,但是要向您证明它实际上没有卡住或冻结,并且它只是无法刷新用户界面,请在循环中添加另一个命令,如下所示:

   :
        listBox1.Items.Add("未找到搜索结果");
        }
        label1.Text = "搜索 = " + listBox1.Items.Count + " 项目," + DateTime.Now.Subtract(dt).TotalSeconds + " s";
       应用程序.DoEvents(); // 添加该行
    } 而 (1==1);

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

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

私人无效按钮6_Click(对象发送者,EventArgs e)
    {
        如果(t == null)
        {
            MessageBox.Show("请点击加载文件按钮。");
            返回;
        }
        if (textBox4.Text == "")
        {
            MessageBox.Show("输入您的布尔查询");
            返回;
        }
        listBox1.Items.Clear();
        日期时间 dt = 日期时间。现在;

        列表 lst = t.ProcessQuery(textBox4.Text);
        计数 = 0;
        如果 (lst != null)
        {
            foreach (int a in lst)
            {
                listBox1.Items.Add(t.documentContentList[count]);
            }
            计数++;
        }
        别的
        {
            listBox1.Items.Add("未找到搜索结果");
        }
        label1.Text = "搜索 = " + listBox1.Items.Count + " 项目," + DateTime.Now.Subtract(dt).TotalSeconds + " s";
    }

现在,每次单击按钮时,它都会调用您的事件处理程序,并且当事件处理程序退出例程时,用户界面将自动更新。因为您的表单是从 System.Windows.Form 类派生的,所以在父类中已经为您实现了保持 Windows 消息泵运行直到用户单击“x”的说明,即您的表单的 System.Windows.Form 类来源于。

当然,在控制台应用程序中并非如此。

于 2013-05-15T08:09:39.460 回答
0

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

于 2013-05-09T14:56:40.013 回答