C# async dispatcher operation not recognized variable 自启动以来已更改
C# async dispatcher operation not recognising variable has changed since it started
我正在尝试实现一种方法,当用户将鼠标光标置于组件中时,该方法将在 WPF 中触发 UI 事件。
行为应该是:
1)鼠标光标进入组件,调用方法mouseEnter
2) 1 秒计时器开始
3) 如果光标还在组件中,则触发事件(本例为打开扩展器)。
最初,这是使用 Thread
完成的,但现在使用 Dispatcher
.
异步执行
当光标进入组件时,一个名为mouseIn
的bool
被设置为true。
当光标离开组件时,mouseIn
设置为 false。
问题是,如果用户将光标放入组件中,然后在 1 秒计时器结束之前将其移出组件,delegate
仍然认为 mouseIn
为真,即使我已经确认一旦光标离开它就会将其设置为 false。
void mouseEnter(object sender, MouseEventArgs e) {
mouseIn = true;
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => {
Thread.Sleep(1000);
if (mouseIn) {
exp.IsExpanded = true;
}
}
}
void mouseLeave(object sender, MouseEventArgs e) {
mouseIn = false;
}
async delegate
通常只保存外部变量启动时的状态吗?
如果是这样,是否有办法强制它重新检查值,或者如果失败,是否有更好的方法来实现此行为?
非常感谢。
您将 Action
安排在 UI 线程上然后阻塞它(尽管您确实使用 BeginInvoke
将其异步排队)并使用 Thread.Sleep
的事实给出mouseLeave
事件处理程序被调用的机会很小。
您可以使用 Task.Delay
获得完全不阻塞消息循环的解决方案。一旦达到 await
,它将把控制权交还给 UI 消息循环,并且一旦延迟结束,将在 UI 线程上安排继续:
async void mouseEnter(object sender, MouseEventArgs e)
{
mouseIn = true;
await Task.Delay(1000);
if (mouseIn)
{
exp.IsExpanded = true;
}
}
void mouseLeave(object sender, MouseEventArgs e)
{
mouseIn = false;
}
mouseIn
变量只有一个副本,代表看到的是同一个变量。问题是你的 mouseLeave
事件没有被调用,因为你的委托中有 Thread.Sleep(1000)
调用。
Dispatcher.BeginInvoke
将在 UI 线程上调用您的操作。然后通过 Thread.Sleep
调用阻塞 UI 线程 1 秒。当 UI 线程处于休眠状态时,它不会响应用户输入,因此不会记录鼠标移动。而不是 Thread.Sleep
使用 async/await
和 Task.Delay
这不会阻塞 UI 线程。
我正在尝试实现一种方法,当用户将鼠标光标置于组件中时,该方法将在 WPF 中触发 UI 事件。
行为应该是:
1)鼠标光标进入组件,调用方法mouseEnter
2) 1 秒计时器开始
3) 如果光标还在组件中,则触发事件(本例为打开扩展器)。
最初,这是使用 Thread
完成的,但现在使用 Dispatcher
.
当光标进入组件时,一个名为mouseIn
的bool
被设置为true。
当光标离开组件时,mouseIn
设置为 false。
问题是,如果用户将光标放入组件中,然后在 1 秒计时器结束之前将其移出组件,delegate
仍然认为 mouseIn
为真,即使我已经确认一旦光标离开它就会将其设置为 false。
void mouseEnter(object sender, MouseEventArgs e) {
mouseIn = true;
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => {
Thread.Sleep(1000);
if (mouseIn) {
exp.IsExpanded = true;
}
}
}
void mouseLeave(object sender, MouseEventArgs e) {
mouseIn = false;
}
async delegate
通常只保存外部变量启动时的状态吗?
如果是这样,是否有办法强制它重新检查值,或者如果失败,是否有更好的方法来实现此行为?
非常感谢。
您将 Action
安排在 UI 线程上然后阻塞它(尽管您确实使用 BeginInvoke
将其异步排队)并使用 Thread.Sleep
的事实给出mouseLeave
事件处理程序被调用的机会很小。
您可以使用 Task.Delay
获得完全不阻塞消息循环的解决方案。一旦达到 await
,它将把控制权交还给 UI 消息循环,并且一旦延迟结束,将在 UI 线程上安排继续:
async void mouseEnter(object sender, MouseEventArgs e)
{
mouseIn = true;
await Task.Delay(1000);
if (mouseIn)
{
exp.IsExpanded = true;
}
}
void mouseLeave(object sender, MouseEventArgs e)
{
mouseIn = false;
}
mouseIn
变量只有一个副本,代表看到的是同一个变量。问题是你的 mouseLeave
事件没有被调用,因为你的委托中有 Thread.Sleep(1000)
调用。
Dispatcher.BeginInvoke
将在 UI 线程上调用您的操作。然后通过 Thread.Sleep
调用阻塞 UI 线程 1 秒。当 UI 线程处于休眠状态时,它不会响应用户输入,因此不会记录鼠标移动。而不是 Thread.Sleep
使用 async/await
和 Task.Delay
这不会阻塞 UI 线程。