【问题标题】:System.Timers.Timer Elapsed Exception handling in Library库中的 System.Timers.Timer Elapsed 异常处理
【发布时间】:2014-06-18 16:33:23
【问题描述】:

我想在我的 WPF 应用程序中处理发生的 System.Timers.Timer elapsed 异常(在我的 DLL 库中)。但我无法做到这一点。它抛出我的 DLL 库,应用程序将崩溃...... 有人知道我该如何解决这个问题吗?

这是我的代码:

public partial class MainWindow : Window
{
    MyClass _myClassInstance = null;

    public MainWindow()
    {
        InitializeComponent();

        try
        {
            _myClassInstance = new MyClass();
        } 
        catch(Exception ex)
        {
            //Here i would like to receive the exception
            //But it never goes in there
            MessageBox.Show(ex.Message);
        }
    }
}

public class MyClass
{
    private System.Timers.Timer _timer = null;

    public MyClass()
    {
        _timer = new Timer();
        _timer.Interval = 2000; //2 Seconds
        _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
        _timer.Start();
        ConnectTo();
    }

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //If timer is elapsed I have to raise an exception
        throw new Exception("It's taking longer than expected. Progress cancelled!");
    }

    private void ConnectTo()
    {
        //Just an example implementation

        //Do something!!
        //Connect to SerialPort and wait for correct response

        //If connected than
        _timer.Stop();
    }
}

【问题讨论】:

    标签: c# exception-handling timer


    【解决方案1】:

    在另一个线程上抛出异常(根据您对 Timing.Timer 的选择)。

    在 1 个程序集中试试这个:你也抓不到它。它在 DLL 中并不重要。

    您只能通过重新思考问题并选择其他解决方案来解决此问题。

    【讨论】:

    • 没错。但是有没有可能解决它呢?或者什么样的概念是进行此类操作的最佳实践。
    • 描述“此类操作”。第一条规则是避免库中的线程和计时器。当你使用它们时,它们应该是完全独立的。
    • 例如:处理如果您尝试在某个时间跨度内连接到设备 (SerialPort) 并且设备响应速度不够快时可能发生的超时。我认为我可以实现一个计时器,启动它,当计时器过去时,我可以引发异常。但是,我们在这里,它不起作用。所以你是完全正确的。我不得不重新思考这个问题。但任何想法都将不胜感激。
    • @user1011394 我已经给出了以下一种方法的确切示例
    【解决方案2】:

    异常发生在事件内部。这是在另一个线程上运行的,因此它永远不会回到原来的线程。

    两种不同的方法。

    1. 您的串行端口 com 库具有某种超时功能(可能),只需使用它即可。
    2. 在单独的步骤上检查您的串行端口。如果您的时间用完了,请终止该线程。

      public class MyClass
      {
          private System.Timers.Timer _timer = null;
          private Thread t;
      
          public MyClass()
          {
              _timer = new Timer();
              _timer.Interval = 2000; //2 Seconds
              _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
              _timer.Start();
              t = new Thread(new ThreadStart(ConnectTo));
              t.Start();
              t.Join();
          }
      
          void _timer_Elapsed(object sender, ElapsedEventArgs e)
          {
              //If timer is elapsed I have to raise an exception
              if (t != null)
                  t.Abort();
          }
      
          private void ConnectTo()
          {
              //Just an example implementation
      
              //Do something!!
              //Connect to SerialPort and wait for correct response
      
              //If connected than
              _timer.Stop();
          }
      }
      

    【讨论】:

    • 这样他就可以杀了它。这就是整个问题。也许你下次应该多读一点代码。
    • 但这是一个附带问题。原来的主要问题呢?
    • 他最初的主要问题是他的计时器异常并没有像他希望的那样在阻塞 I/O 时杀死他。
    • 但是你不认为 MainWindow 想继续吗?
    【解决方案3】:

    作为一种替代方法,您可以使用事件来代替使用异常来控制您的应用程序流程,例如

    public partial class MainWindow : Window
    {
        MyClass _myClassInstance = null;
    
        public MainWindow()
        {
            InitializeComponent();
            _myClassInstance = new MyClass();
            _myClassInstance.TimedOut += delegate (object sender, EventArgs e) {
                ((MyClass)sender).CancelConnect();
                MessageBox.Show("Timeout!");
            };
            _myClassInstance.ConnectTo();
        }
    }
    
    ...
    
    public class MyClass
    {
        Timer _timer = new Timer();
    
        public event EventHandler TimedOut;
    
        void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            OnTimedOut();
        }
    
        private void OnTimedOut()
        {
            var handler = TimedOut;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    
        public void ConnectTo(int timeout = 2000)
        {
            CancelConnect();
            _timer.Interval = timeout; // pass timeout in so it's flexible
            _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
            _timer.Start();
            // do connect stuff...
            _timer.Stop();
        }
    
        public void CancelConnect()
        {
            _timer.Stop();
            // cancel connect stuff...
        }
    }
    

    我认为您在 MyClass 的构造函数中进行了太多操作,因此我将其移至您直接从 MainWindow 调用的 ConnectTo 中。

    【讨论】:

    • 他应该如何使用这个和他的可能阻塞的连接东西?我已经用下面的线程回答了如何做到这一点,使用事件是多余的。
    • @CrazyCasta 没有ConnectTo 的实际来源,您的假设 就是这样。此解决方案只是确保通知MainWindow 如果 计时器运行(这表明存在超时)。定时器在不同的线程上运行,所以即使 ConnectTo 东西阻塞了 UI 线程,它也不会阻塞定时器。
    【解决方案4】:

    不工作:

    MessageBox.Show(e.Message);多恩投掷

    public class MyClass
    {
        private System.Timers.Timer _timer = null;
        private Thread t;
    
        public MyClass()
        {
            try
            {
            _timer = new System.Timers.Timer();
            _timer.Interval = 5000; //2 Seconds
            _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
            _timer.Start();
            t = new Thread(new ThreadStart(ConnectTo));
            t.Start();
            t.Join();
            }
            catch (Exception e)
            {
    
                MessageBox.Show(e.Message);
            }
        }
    
        void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            //If timer is elapsed I have to raise an exception
            if (t != null)
            {
                t.Abort();
            }
        }
    
        private void ConnectTo()
        {
            //Just an example implementation
    
            //Do something!!
            try
            {
                //Connect to SerialPort and wait for correct response
                using (SqlConnection _SC = new SqlConnection("aaaa"))
                {
                    _SC.Open();
                }
            }
            catch (Exception)
            {
    
                throw;
            }
            finally
            {
                //If connected than
                _timer.Stop();
            }
    
    
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 2020-04-27
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      相关资源
      最近更新 更多