代码之家  ›  专栏  ›  技术社区  ›  X.Otano

等待异步事件处理程序不等待方法继续

  •  1
  • X.Otano  · 技术社区  · 8 年前

    我正在开发一个 Winforms应用程序 . 我创建了一个自定义控件(继承自 控制装置 类)。它有自己的事件处理程序,允许窗体观察某些事件。

    public  event EventHandler<TextBoxFilterEventArgs> DataGetFiltered;
    

    我的问题是,在控件内部,在某些特定情况下,我对注册的接收器执行调用:

    this.Enabled=false;
    if (DataGetFiltered != null)
       DataGetFiltered(this, new TextBoxFilterEventArgs(itemsFiltered));
    this.Enabled=true;
    

    您可以看到我在调用前后设置了禁用/启用控件。 包含控件的窗体正在以异步方式向该事件注册某些方法:

    txtFilter.DataGetFiltered += async (s, e) => await txtFilterByDesc_DataGetFiltered(s, e);
    
    private async Task txtFilterByDesc_DataGetFiltered(object sender, TextBoxFilterEventArgs e)
    {
         await Task.Run(()=>/*some code*/);
    }
    

    会发生什么? 控件调用注册的事件处理程序,但它继续运行 this.Enabled=true; 没有等待前一个呼叫完成(但它已经被等待!) 发生什么事?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Dennis    8 年前

    会发生什么?

    禁用控件后,事件处理代码将运行异步委托。
    代表最终要求 Task.Run 并将一些工作卸载到线程池线程。 然后委托返回,控件再次启用,但计划的任务仍在后台运行。

    控件是一个文本框,我希望在处理事件处理程序期间启用/禁用它。我必须把逻辑转移到处理程序本身?

    简短回答:是的。

    更详细的答案是:在使用标准的.NET事件处理模式时,必须将此逻辑移到事件处理程序中。事件不知道处理程序实现。它们可以是同步的,也可以是异步的。所以,您所能做的就是让事件处理程序管理 Enabled 财产。

    从技术上讲,您可以发明某种异步事件处理程序,但实际上,您不应该..net开发人员知道,事件委托是 EventHandler / EventHandler<T> . 自定义事件委托类型打破了众所周知的模式。

        2
  •  1
  •   Chayim Friedman    8 年前

    我想是因为 事件处理程序 使用 await ,但你的 调用的方法 别等处理人!因此,您需要创建自己的返回事件 Task ,如下所示:

    public delegate Task DataGetFiltered(object sender, TextBoxFilterEventArgs e);
    public event DataGetFiltered OnDataGetFiltered;
    

    在被调用的方法中:

    if (null != this.OnDataGetFiltered)
    {
        var args = new TextBoxFilterEventArgs(itemsFiltered);
        foreach (var handler in this.OnDataGetFiltered.GetInvocationList().Cast<DataGetFiltered>())
        {
            await handler(this, args);
        }
    }