我需要一个小功能,等待释放左侧按钮,而不是基于MouseUp event
。
在许多情况下,当我们需要这个时,我们只需为MouseUp event
编写一个事件处理程序
它很简单,而且很有效。
然而,有些情况下使用MouseUp event
无效,
例如,当我们已经在另一个(不同的)事件处理程序中时,
调用此事件处理程序时可能会按下鼠标左键,我们需要等待它被释放。
(目标是拥有一个代码流,而不必在几个可能已被其他代码占用的地方之间拆分)
我是这样实现的:
public void WaitForMouseUp()
{
while( (Control.MouseButtons&MouseButtons.Left)!=0 )
Application.DoEvents();
}
它有效,
例如,当您在Control.Enter
事件的事件处理程序中时,可以使用它
如果通过鼠标输入控件,则此功能将被阻止,直到释放鼠标按钮。
我只担心一件事:
我在那里使用Application.DoEvents()
,我想知道是否有其他方式而不是使用Application.DoEvents()
。
(Application.DoEvents();具有可能的重入性的缺点,因此,因此我尽量减少使用它,尽可能减少使用它)
任何人都知道我可以替换Application.DoEvents()
部分吗?
答案 0 :(得分:2)
这是一个很棒的方式来做你要问的事情。使用Microsoft的Reactive Extensions使一行代码可以执行您想要的任何操作。
反应式扩展提供了大量可应用于事件的运算符。
首先是一些与正常控制事件直接相关的基本可观察量:
var mouseEnters =
Observable
.FromEventPattern(
h => button1.MouseEnter += h,
h => button1.MouseEnter -= h);
var mouseLeaves =
Observable
.FromEventPattern(
h => button1.MouseLeave += h,
h => button1.MouseLeave -= h);
var mouseUps =
Observable
.FromEventPattern<MouseEventHandler, MouseEventArgs>(
h => button1.MouseUp += h,
h => button1.MouseUp -= h);
现在我们需要一个只在鼠标出现时才会触发一次的查询,但前提是鼠标已经输入button1
,但只有在它离开之前。
var query =
mouseEnters
.Select(me => mouseUps.Take(1).TakeUntil(mouseLeaves))
.Switch();
现在订阅该事件以便能够处理它:
var subscription =
query
.Subscribe(ep =>
{
/*
this code runs for the first mouse up only
after each mouse enter on `button1`
unless the mouse leaves `button1`
*/
});
现在因为subscription
的类型为IDisposable
而取消订阅非常简单。所以你只需致电subscription.Dispose();
。
只需NuGet“Rx-WinForms”来获取项目的位数。
答案 1 :(得分:2)
事实上@Kai Brummund建议的是我answer到Force loop to wait for an event的变体。从那里为MouseUp调整代码很简单,如
public static class Utils
{
public static Task WhenMouseUp(this Control control)
{
var tcs = new TaskCompletionSource<object>();
MouseEventHandler onMouseUp = null;
onMouseUp = (sender, e) =>
{
control.MouseUp -= onMouseUp;
tcs.TrySetResult(null);
};
control.MouseUp += onMouseUp;
return tcs.Task;
}
}
,用法是
Control c = ...;
await c.WhenMouseUp();
同样的技术可以用于任何事件。
答案 2 :(得分:1)
如果您不想在单个方法中编写流程,则可以使用TaskCompletionSource进行等待。
你的流程:
await MouseUp();
...
private Task MouseUp() {
_tcs = new TaskCompletionSource();
return _tcs.Task;
}
public ... OnMouseUpEvent() {
_tcs?.SetResult(true);
}
对于伪代码感到抱歉,一旦我得到移动设备以外的其他内容,我们就会更新。
答案 3 :(得分:0)
我需要一个小功能,等待鼠标的左键被释放。
不,不。 WinForms GUI编程是事件驱动的,异步的。您应该使用MouseUp
事件来检测鼠标按钮的释放。这意味着您需要使用基于状态的异步技术来实现逻辑,而不是您渴望的同步模型。