У меня есть созданный поток, в котором запущен диспетчер для обработки событий с ловушками мыши низкого уровня, и создан DispatcherTimer на основе этого диспетчера.
Когда DispatcherTimer.Tick() был запущен, я смоделировал еще одно сообщение с нажатой мышью. Затем произошло нечто странное: Dispatcher.Tick() был прерван, и в том же потоке сработало событие перехвата мыши. После обработки события перехвата мыши DispatcherTimer.Tick() продолжает завершаться.
Насколько я понимаю, диспетчер будет обрабатывать задачи одну за другой, поэтому он должен полностью выполнить метод DispatcherTimer.Tick(), а затем другие события ловушки.
Это поведение нормально? Могу ли я в любом случае гарантировать, что DispatcherTimer.Tick() был полностью выполнен до запуска события ловушки?
Создание потока диспетчера:
public static class DispatcherBuilder
{
public static Dispatcher Build()
{
Dispatcher dispatcher = null;
var manualResetEvent = new ManualResetEvent(false);
var thread = new Thread(() =>
{
dispatcher = Dispatcher.CurrentDispatcher;
var synchronizationContext = new DispatcherSynchronizationContext(dispatcher);
SynchronizationContext.SetSynchronizationContext(synchronizationContext);
manualResetEvent.Set();
try
{
Dispatcher.Run();
}
catch
{
// ignore
}
}, maxStackSize:1);
thread.Priority = ThreadPriority.Normal;
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
manualResetEvent.WaitOne();
manualResetEvent.Dispose();
return dispatcher;
}
}
Код для создания таймера и настройки хука:
// creating disapatcher:
_hookDispatcher = DispatcherBuilder.Build();
// creating timer on the dispatcher
_mouseDownTimer = new DispatcherTimer(DispatcherPriority.Normal, _hookDispatcher);
_mouseDownTimer.Tick += new EventHandler(mouseDownTimer_Tick);
_mouseDownTimer.Interval = TimeSpan.FromMilliseconds(_dataService.Settings.RightBtnPopupDelayMs);
// create hook
_hookDispatcher.Invoke(() =>
{
_mouseHook = new MouseHook();
_mouseHook.MouseUp += MouseHookOnMouseUp;
_mouseHook.MouseDown += MouseHookOnMouseDown;
_mouseHook.MouseWheel += MouseHookOnMouseWheel;
_mouseHook.MouseMove += MouseHookOnMouseMove;
_mouseHook.MouseHWheel += MouseHookOnMouseHWheel;
_mouseHook.Start();
});
Ниже приведен некоторый вывод Debug.WriteLine():
177,250 MouseDown Right Thread:14
177,250 MouseDown Right Captured Thread:14
// DeispatcherTimer.Tick() Started
177,360 Timer Tick Begin Thread:14 -- in DeispatcherTimer.Tick()
177,360 Sending RightButtonDown -- in DeispatcherTimer.Tick()
// MouseHookOnMouseUp() called in same thread
177,485 MouseUp Right Thread:14 -- in MouseHookOnMouseUp()
177,500 MouseUp Right Captured Thread:14 -- in MouseHookOnMouseUp()
// MouseHookOnMouseDown() called in same thread
177,500 MouseDown Right Thread:14 -- in MouseHookOnMouseDown()
// Returned to DeispatcherTimer.Tick() in same thread
177,500 Timer Tick End -- in DeispatcherTimer.Tick()
177,500 MouseDown Right Thread:14