【问题标题】:Textbox typing hangs the UI in Winforms C#文本框键入会在 Winforms C# 中挂起 UI
【发布时间】:2017-04-27 10:59:29
【问题描述】:

我正在制作一个应用程序,其中有一个 tabControl 和一些我想创建的控件。所以我有一个基本上可以制作控件和文本框的功能。代码如下所示:

TextBox message_box = new TextBox();
message_box.Size = new Size(790, 38);
message_box.Location = new Point(9, 7);
message_box.Font = new Font("Microsoft Sans Serif", 20);
message_box.KeyDown += Message_box_KeyDown;
message_box.Enter += Message_box_Enter;
bottom_panel.Controls.Add(message_box);

我还添加了一些其他控件,但这个特定控件是我遇到问题的控件。因为当我将这些控件添加到标签页,然后我将标签页添加到标签控件时,会发生一些奇怪的事情。

添加的 tabPage 中的每个控件都可以正常工作,并且没有延迟。但是当我输入文本框时,我得到了很大的延迟并且它冻结了。如果我也将文本框添加到 tabControl 中的设计器创建页面,也会发生这种情况。

这是被触发的事件:

private async void Message_box_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyData == Keys.Enter)
    {
        string name = "";
        this.Invoke(new MethodInvoker(delegate { name = tabControl1.SelectedTab.Name; }));
        TextBox box = new TextBox();
        this.Invoke(new MethodInvoker(delegate {  box = (TextBox)sender; }));
        if (box.Text.Length > 0)
        {
            uiControls.ListItem melding = await Task.Factory.StartNew(() => sendMelding(name, box.Text));
            box.Clear();
        }
    }
}

我不知道我做错了什么,以及如何使文本框停止滞后。我试图检查它是否需要调用,我尝试过调用。我也使用了这段代码,将 CreateParams 改写为:

protected override CreateParams CreateParams
{
    get
    {
        // add the drop shadow flag for automatically drawing
        // a drop shadow around the form
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        cp.ClassStyle |= CS_DROPSHADOW;
        return cp;
    }
}

需要明确的是,KeyDown 函数对性能没有影响,KeyDown 函数中的代码不会在我每次编写时触发,它仅在我按 Enter 时触发。但是通常如果我在文本框中写了大约 2-3 个字符,则滞后开始出现并且程序冻结,如果我删除它也会发生的事件。

【问题讨论】:

  • sendMelding 的功能是什么?每次你的文本框有数据时都需要调用sendMelding方法吗?
  • 输入是否只有在您按下 Enter 键或每次按键时才会延迟?
  • 即使您调用 KeyDown 事件,您是否有延迟?
  • 可能是StartNew方法的问题。见this
  • 是的,无论按键事件如何,我都有延迟

标签: c# winforms visual-studio tabcontrol


【解决方案1】:

我怀疑出现延迟是因为您在继续等待任务完成。也就是说,你有:

if (box.Text.Length > 0)
{
    uiControls.ListItem melding = await Task.Factory.StartNew(() => sendMelding(name, box.Text));
    box.Clear();
}

在任务完成之前不会执行对box.Clear 的调用。

很难说你将如何解决这个问题,因为我不知道你想在这里完成什么。

此外,您需要检查您在该方法中对Invoke 的使用。你有一些错误。例如,您访问 box.Text.Length 而没有 Invoking,这意味着如果在非 UI 线程上调用事件处理程序,您将得到一个异常。

【讨论】:

  • KeyDown 事件中的代码仅在我按 Enter 时触发。但是无论有没有事件,都会发生滞后和冻结
  • 我也知道由于跨线程调用而引发的异常。但是无论事件及其算法如何,文本框的延迟和冻结都会发生。
  • 那么如果你把回车时执行的所有代码都注释掉了,那么滞后还存在吗?如果是这样,那么KeyDown 事件可能不是罪魁祸首,您应该在其他地方寻找问题。
猜你喜欢
  • 1970-01-01
  • 2021-04-15
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多