【问题标题】:Prevent raising next events in a async event防止在异步事件中引发下一个事件
【发布时间】:2014-09-29 02:18:06
【问题描述】:

执行 GetDataAsync 时,会在 textbox1_Leave 事件完成之前引发 textBox1_Validating 事件。我该怎么做才能防止这种情况发生?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private bool IsValid = true;

    private async void textBox1_Leave(object sender, EventArgs e)
    {
        MessageBox.Show("Working");

        ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
        IsValid = await client.CheckUser(textBox1.Text);

    }

    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        if(IsValid)
            MessageBox.Show("Welcome!");
        else
            e.Cancel = true;
    }
}

【问题讨论】:

  • 你不能(除非你让它同步)
  • 您如何称呼这些事件?通过TextBox?
  • 您是否考虑过Leave 事件可能不是最好的地方?也许如果您解释一下您要做什么,我们可以帮助您找到另一个解决方案。
  • @James 我改变了我的问题。

标签: c# .net winforms task-parallel-library async-await


【解决方案1】:

来自Control.Validating

事件按以下顺序发生:

  1. 输入

  2. 获得焦点

  3. 离开

  4. 验证

  5. 已验证

  6. 失焦

当您在Control.Leave 中使用await 时,您让UI 消息泵继续执行,因此它会处理下一个事件。如果您想等到Leave 完成,请同步运行您的方法。

【讨论】:

  • 如果我同步运行方法,我的表单会冻结,直到方法完成。这是个坏主意。我能做什么?
  • 您无法从TextBox 事件中运行此代码。你想做什么?
  • 我想在服务工作时显示一个等待面板。
  • 那为什么要在文本框 valudate 方法中设置它呢?创建一个在工作完成时通知用户的方法
  • 我想在服务启动时显示(showdialog)一个加载表单,并在它完成时隐藏它。如果我同步运行方法,所有表单都会挂起并冻结,直到方法完成。
【解决方案2】:

控件的Validating 进程是一个同步进程,不能让它等到从异步方法返回后再继续。 async / await 的要点是允许 UI 在您等待异步方法的结果时继续运行,因此一旦您在 Leave 事件中 await 时,控件将假定它已完成并继续执行其余操作事件链。

Validating 事件应该用于执行同步验证,如果你需要服务器验证那么你只需要接受输入的文本有效然后Validated 事件你可以发送你的请求

private bool IsValid = false;

private void textBox1_Validated(object sender, EventArgs e)
{
    this.ValidateUser(textBox1.Text);
}

private async void ValidateUser(string username)
{
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    IsValid = await client.CheckUser(textBox1.Text);
    if (IsValid) {
        MessageBox.Show("Welcome!");
    } else {
        MessageBox.Show("Invalid Username, try again!");
        textBox1.Focus();
    }
}

【讨论】:

  • 我要设置 e.Cancel = true;在文本框验证事件中。
  • @ArMaN 好吧,不幸的是,你不能。我已经在回答中解释了为什么你不能这样做。
  • @ArMaN 我的回答仍然会给你异步,它只是不使用Validating 事件来做到这一点。如果您真的不想阻止 UI,那么您需要接受 Validating 事件不是执行此操作的正确位置。
猜你喜欢
  • 1970-01-01
  • 2011-09-11
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多