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

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

问题描述

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

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

public void StartMethod()
{
...
SecondaryThread.Start(); //启动次要线程
}

private void SecondaryThreadMethod()
{
...
OperationFinished(null,new EventArgs());
... //这是程序在触发OperationFinished时等待任何操作取
//的地方。
}

}

此代码是API的一部分我的一个设备。当OperationFinished事件被触发时,我希望客户端应用程序能够执行所需的任何操作(即相应地更新GUI),而不会窃取API操作。



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

解决方案

所以你想以一种防止监听者阻止的方式来引发事件后台线程? im me几分钟,举起一个例子;这很简单: - )



这里我们去:首先是重要的说明!每当你打电话 BeginInvoke 你必须调用相应的 EndInvoke ,否则如果调用的方法抛出异常,那么返回一个值,那么ThreadPool线程永远不会释放回池,导致线程泄漏!

  class TestHarness 
{

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

//模拟一些事件监听器
raiser.SomeEvent + =(sender,e)=> {Console.WriteLine(Received event); };
raiser.SomeEvent + =(sender,e)=>
{
//糟糕的听众!
Console.WriteLine(Blocking event);
System.Threading.Thread.Sleep(5000);
Console.WriteLine(完成阻塞事件);
};

//抛出异常的侦听器
raiser.SomeEvent + =(sender,e)=>
{
Console.WriteLine(Received event,time to die!);
抛出新的异常();
};

//提高事件,看效果
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); (int index = 0; index< eventListeners.Count(); index ++)
{
var methodToInvoke =(EventHandler)eventListeners [index];
methodToInvoke.BeginInvoke(this,EventArgs.Empty,EndAsyncEvent,null);
}
Console.WriteLine(完成提升事件);
}
}

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

try
{
invokedMethod.EndInvoke(iar);
}
catch
{
//处理被调用方法抛出的任何异常
Console.WriteLine(事件监听器去了kaboom!);
}
}
}


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.
  }

}

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.

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 :-)

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天全站免登陆