如何使事件处理程序异步运行? [英] How do I make an eventhandler run asynchronously?

查看:19
本文介绍了如何使事件处理程序异步运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个在辅助线程上执行连续循环操作的 Visual C# 程序.有时,当该线程完成任务时,我希望它触发事件处理程序.我的程序会这样做,但是当事件处理程序被触发时,辅助线程会等到事件处理程序完成后再继续线程.我如何让它继续?这是我目前的结构方式......

I am writing a Visual C# program that executes a continuous loop of operations on a secondary thread. Occasionally when that thread finishes a task I want it to trigger an eventhandler. My program does that but the when the event handler is triggered, the secondary thread waits until the event handler is finished before continuing the thread. How do I make it continue? Here is the way I currently have it structured...

class TestClass 
{
  private Thread SecondaryThread;
  public event EventHandler OperationFinished;

  public void StartMethod()
  {
    ...
    SecondaryThread.Start();      //start the secondary thread
  }

  private void SecondaryThreadMethod()
  {
    ...
    OperationFinished(null, new EventArgs());
    ...  //This is where the program waits for whatever operations take
         //place when OperationFinished is triggered.
  }

}

此代码是我的一台设备的 API 的一部分.当 OperationFinished 事件被触发时,我希望客户端应用程序能够做它需要做的任何事情(即相应地更新 GUI)而不需要拖拽 API 操作.

This code is part of an API for one of my devices. When the OperationFinished event is triggered I want the client application to be able to do whatever it needs to (i.e. update the GUI accordingly) without haulting the API operation.

另外,如果我不想将任何参数传递给事件处理程序,使用 OperationFinished(null, new EventArgs()) 的语法是否正确?

Also, if I do not want to pass any parameters to the event handler is my syntax correct by using OperationFinished(null, new EventArgs()) ?

推荐答案

所以你想以一种防止监听器阻塞后台线程的方式引发事件?给我几分钟的时间来举个例子;这很简单:-)

So you want to raise the event in a manner that prevents the listeners from blocking the background thread? Gimme a couple minutes to whip up an example; it's pretty simple :-)

我们开始:首先要注意!每当你调用BeginInvoke时,你必须调用相应的EndInvoke,否则如果调用的方法抛出一个异常返回一个值,那么 ThreadPool 线程将永远不会被释放回池中,导致线程泄漏!

Here we go: first an important note! Whenever you call BeginInvoke you must call the corresponding EndInvoke, otherwise if the invoked method threw an exception or returned a value then the ThreadPool thread will never be released back to the pool, resulting in a thread-leak!

class TestHarness
{

    static void Main(string[] args)
    {
        var raiser = new SomeClass();

        // Emulate some event listeners
        raiser.SomeEvent += (sender, e) => { Console.WriteLine("   Received event"); };
        raiser.SomeEvent += (sender, e) =>
        {
            // Bad listener!
            Console.WriteLine("   Blocking event");
            System.Threading.Thread.Sleep(5000);
            Console.WriteLine("   Finished blocking event");
        };

        // Listener who throws an exception
        raiser.SomeEvent += (sender, e) =>
        {
            Console.WriteLine("   Received event, time to die!");
            throw new Exception();
        };

        // Raise the event, see the effects
        raiser.DoSomething();

        Console.ReadLine();
    }
}

class SomeClass
{
    public event EventHandler SomeEvent;

    public void DoSomething()
    {
        OnSomeEvent();
    }

    private void OnSomeEvent()
    {
        if (SomeEvent != null)
        {
            var eventListeners = SomeEvent.GetInvocationList();

            Console.WriteLine("Raising Event");
            for (int index = 0; index < eventListeners.Count(); index++)
            {
                var methodToInvoke = (EventHandler)eventListeners[index];
                methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, null);
            }
            Console.WriteLine("Done Raising Event");
        }
    }

    private void EndAsyncEvent(IAsyncResult iar)
    {
        var ar = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
        var invokedMethod = (EventHandler)ar.AsyncDelegate;

        try
        {
            invokedMethod.EndInvoke(iar);
        }
        catch
        {
            // Handle any exceptions that were thrown by the invoked method
            Console.WriteLine("An event listener went kaboom!");
        }
    }
}

这篇关于如何使事件处理程序异步运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆