如何在WPF中处理System.Threading Timer事件

时间:2011-11-08 22:58:25

标签: wpf multithreading events timer

我根据以下代码在类对象中创建了一个Timer事件处理程序。:

    public class MyTimerClass
    {
        private Timer _timeoutTimer;

        private void Constructor()
        {
           _timeoutTimer = new Timer(TimerHandler, null, 0, 1000);
        }

        private void TimerHandler()
        {
            if (Something) 
                LogMessage(LogLevel.Error, "Timeout Waiting...");
        }
    }

我在同一个类对象中创建了一个带有委托的LogMessageHandler事件来处理计时器事件和其他日志事件:

    public delegate void LogMessageHandler(LogLevel logLevel, string message);
    public event LogMessageHandler OnLogMessage;

    private void LogMessage(LogLevel logLevel, string message)
    {
      if (OnLogMessage != null)
        OnLogMessage(logLevel, message);
    }

在另一个类中,我想处理为计时器派生的日志消息。这是我对OnLogMessage事件的订阅以及处理该线程的类:

        void InitializeMyTimerClass()
        {
            try
            {
                _myTimerClass = new MyTimerClass();
                _myTimerClass.OnLogMessage += new LogMessageHandler(UpdateLogMessage);
            }
            catch (Exception ex)
            {
                _dialog.ShowException(ex.Message);
            }
        }

        private void UpdateLogMessage(LogLevel newLogLevel, string message)
        {
            TaskScheduler schedulerForLog = TaskScheduler.FromCurrentSynchronizationContext();

            Task.Factory.StartNew(() => TrackResponseMessage.Add(FormatLogLevelToString(newLogLevel) + ": " + message),
            CancellationToken.None, TaskCreationOptions.None, schedulerForLog);
        }

当我运行代码并发生计时器事件时,我在创建TaskScheduler的位置设置了一个断点:TaskScheduler schedulerForLog = TaskScheduler.FromCurrentSynchronizationContext(); LogLevel和字符串参数已成功从MyTimerClass传递。但是,当TaskScheduler尝试获取当前同步上下文时,我收到InvalidOperationException。似乎来自计时器线程的SynchronizationContext对于TaskScheduler是不可接受的。

问题:计时器事件是否在单独的线程中传递?在这种情况下,处理计时器线程的最佳方法是什么?有人可以提供演示代码吗? ...谢谢!

1 个答案:

答案 0 :(得分:2)

如果您的问题是跨线程无效操作,则可以使用Application.Current.Dispatcher调用要在应用程序主线程中运行的进程以避免此问题:

    private void UpdateLogMessage(LogLevel newLogLevel, string message)
    {
        Application.Current.Dispatcher.BeginInvoke(new Action(()=>{
            TaskScheduler schedulerForLog = TaskScheduler.FromCurrentSynchronizationContext();

            Task.Factory.StartNew(() => TrackResponseMessage.Add(FormatLogLevelToString(newLogLevel) + ": " + message),
            CancellationToken.None, TaskCreationOptions.None, schedulerForLog);
        });
    }

如果主线程不是您需要的线程,那么您需要保留所需线程的调度程序并从那里调用。