Как обработать событие System.Threading Timer в WPF - PullRequest
0 голосов
/ 09 ноября 2011

Я создал обработчик события 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 и string успешно передаются из MyTimerClass.Тем не менее, я получаю InvalidOperationException, когда TaskScheduler пытается получить текущий контекст синхронизации.Похоже, что SynchronizationContext из потока таймера неприемлемо для TaskScheduler.

Вопрос. Передается ли событие таймера в отдельном потоке?Каков наилучший способ обработки потока таймера в этом случае?Может кто-нибудь предоставить демо-код?... Спасибо!

1 Ответ

2 голосов
/ 09 ноября 2011

Если ваша проблема - недопустимая операция между потоками, вы можете использовать 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);
        });
    }

Если основной поток - это не тот поток, который вам нужен, вам нужно взять диспетчер для нужного потока и вызвать его оттуда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...