Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf Dispatchermer.Tick被同一线程中的鼠标挂钩事件中断_Wpf_Dispatchertimer - Fatal编程技术网

Wpf Dispatchermer.Tick被同一线程中的鼠标挂钩事件中断

Wpf Dispatchermer.Tick被同一线程中的鼠标挂钩事件中断,wpf,dispatchertimer,Wpf,Dispatchertimer,我创建了一个线程,该线程运行一个调度程序来处理低级鼠标挂钩事件,并基于该调度程序创建了一个调度程序 当Dispatchermer.Tick被激活时,我模拟了另一条鼠标按下的消息。然后发生了一件奇怪的事: Dispatcher.Tick被中断,并在同一线程中触发鼠标挂钩事件。处理鼠标钩子事件后,Dispatchermer.Tick继续结束 据我所知,调度器将逐个处理任务,因此它应该完全执行dispatchermer.Tick方法,然后执行其他钩子事件 这种行为正常吗? 我是否可以确保Dispatc

我创建了一个线程,该线程运行一个调度程序来处理低级鼠标挂钩事件,并基于该调度程序创建了一个调度程序

当Dispatchermer.Tick被激活时,我模拟了另一条鼠标按下的消息。然后发生了一件奇怪的事: Dispatcher.Tick被中断,并在同一线程中触发鼠标挂钩事件。处理鼠标钩子事件后,Dispatchermer.Tick继续结束

据我所知,调度器将逐个处理任务,因此它应该完全执行dispatchermer.Tick方法,然后执行其他钩子事件

这种行为正常吗? 我是否可以确保Dispatchermer.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


一切似乎都很好

当Dispatchermer.Tick被激活时,我模拟了另一只鼠标 消息然后奇怪的事情发生了:调度员。滴答声是 在同一线程中触发中断和鼠标挂钩事件。[……]

一般情况下,事件处理程序在引发事件的同一线程上执行,但执行由事件源或处理程序本身封送到不同的线程。 由于已显式地将Dispatcher设置为在_hookDispatcher上运行,因此引发事件的Tick处理程序在_hookDispatcher线程上运行。因此,Tick处理程序和该处理程序引发的所有事件及其相应的事件处理程序都在同一个线程上执行,即与Dispatcher关联的线程

这回答了您的第一个问题,即为什么事件处理程序在Dispatcher执行的同一线程上执行

[…]在处理鼠标挂钩事件后 调度程序。勾号继续结束

据我所知,调度员将逐个处理任务, 所以它应该完全执行dispatchermer.Tick方法, 然后是其他钩子事件

事件始终以同步方式引发,WPF不实现异步事件

1将执行勾号处理程序。 2此处理程序引发鼠标事件。 3事件委托被同步调用,这意味着Tick处理程序的继续被挂起。 4调用鼠标事件委托意味着也调用所有已注册的回调。 5调用最后一次回调后,Tick处理程序可以继续执行

所以你的观察是正确的,但在这种情况下,这种行为是绝对正常的

如果希望勾号处理程序在处理鼠标事件时继续执行,则应在后台线程上引发鼠标事件。但由于处理输入事件是为了执行与UI相关的工作,因此这些处理程序很可能会调用Dispatcher来访问UI资源或任何DispatcherObject。在后台线程上执行这样的处理程序,强制处理程序再次与UI线程同步代价太高,通常没有任何意义

建议的解决方案是使用Dispatcher.InvokeAsync引发事件:


Dispatcher.InvokeAsync执行异步。因此,控件在被调用后会立即返回到调用对象Tick处理程序。

能否共享代码示例?@PavelAnikhouski I'v添加一些代码,谢谢。
private void OnTick(object sender, EventArgs e)
{
  Dispatcher.InvokeAsync(RaiseMouseEvent, DispatcherPriority.Background);
}