Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步引发事件_C#_.net_Winforms - Fatal编程技术网

C# 异步引发事件

C# 异步引发事件,c#,.net,winforms,C#,.net,Winforms,我正在研究在一个组件中执行异步事件调度的选项,该组件有许多事件订阅服务器。在仔细阅读这些选项时,我遇到了以下示例: public event ValueChangedEvent ValueChanged; public void FireEventAsync(EventArgs e) { Delegate[] delegates = ValueChanged.GetInvocationList(); foreach (Delegate d in delegates) {

我正在研究在一个组件中执行异步事件调度的选项,该组件有许多事件订阅服务器。在仔细阅读这些选项时,我遇到了以下示例:

public event ValueChangedEvent ValueChanged;
public void FireEventAsync(EventArgs e)
{
    Delegate[] delegates = ValueChanged.GetInvocationList();
    foreach (Delegate d in delegates)
    {
        ValueChangedEvent ev = (ValueChangedEvent)d;
        ev.BeginInvoke(e, null, null);
    }
}
除了较旧的语法(示例来自.NET1.1),在我看来这是一个严重的资源泄漏。没有完成方法,没有完成轮询,也没有调用
EndInvoke
的任何其他方式

我的理解是,每个
BeginInvoke
都必须有相应的
EndInvoke
。否则,将有挂起的
AsyncResult
对象实例浮动,以及(可能)在异步事件期间引发的异常

我意识到,通过提供回调并执行
EndInvoke
,很容易改变这一点,但如果我不需要

处理异步实例完全是另一回事,再加上需要与UI线程同步(即,
invokererequired
,等等),可以很好地支持执行这些异步通知的整个想法

因此,有两个问题:

  • 我认为每个
    BeginInvoke
    都需要一个相应的
    EndInvoke
    ,对吗
  • 除了上面提到的以外,在Windows窗体应用程序中执行异步事件通知还有其他陷阱吗
  • 否。仅当指定了返回类型时才需要EndInvoke。请查看以下内容:。另外,我发布了这篇半相关的文章

  • 我真的帮不了你!:-)对不起


  • BeginInvoke()
    的调用应与
    EndInvoke()
    配对,但不这样做不会导致资源泄漏。
    BeginInvoke()
    返回的
    IAsyncResult
    将被垃圾收集

    这段代码中最大的陷阱是,在终止应用程序时,您很容易遇到异常。您可能希望将委托调用包装在异常处理程序中,并考虑如何传播发生的异常(报告第一个异常、生成聚合异常等)


    使用
    BeginInvoke()
    调用deltage将从线程队列中删除一个线程以开始运行事件。这意味着事件将始终从主UI线程触发。这可能会使某些事件处理程序场景更难处理(例如,更新UI)。处理程序需要意识到他们需要调用
    SynchronizationContext.Send()
    .Post()
    与主UI线程同步。当然,所有其他多线程编程陷阱也适用。

    在思考了一段时间后,我得出结论,在Windows窗体控件中执行异步事件可能不是一个好主意。应在UI线程上引发Windows窗体事件。否则会给客户机带来不必要的负担,并可能导致
    AsyncResult
    对象和异步异常混乱

    让客户端启动自己的异步处理(使用
    BackgroundWorker
    或其他一些技术)或同步处理事件更为简洁


    当然也有例外<例如,code>System.Timers.Timer会在线程池线程上引发
    已用
    事件。但是,最初的通知会出现在池线程中。看起来一般的规则是:在获得初始通知的同一线程上引发事件。至少,这是最适合我的规则。这样,泄漏对象就毫无疑问了。

    为什么要异步调度?您是否做过性能分析,表明这将是有益的?如果不是,多个线程可能会使情况变得更糟。是的,我已经做了性能分析,以确定异步处理是否会带来好处。不幸的是,MSDN线程不是确定的,但它为我提供了一些可以跟踪这一点的指针。是的,客户端(即事件订阅者)的要求准备好处理池线程上的通知在这里很可能是一个杀手。我认为客户端应该异步订阅,如果他们愿意的话,而不是让控制强制订阅。