WPF 中的 Application.DoEvents() 在哪里?
我有以下示例代码,每次按下按钮时都会缩放:
XAML:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="myCanvas">
<Canvas.LayoutTransform>
<ScaleTransform x:Name="myScaleTransform" />
</Canvas.LayoutTransform>
<Button Content="Button"
Name="myButton"
Canvas.Left="50"
Canvas.Top="50"
Click="myButton_Click" />
</Canvas>
</Window>
*.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
myScaleTransform.ScaleX =
myScaleTransform.ScaleY =
myScaleTransform.ScaleX + 1;
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
}
private Point GetMyByttonLocation()
{
return new Point(
Canvas.GetLeft(myButton),
Canvas.GetTop(myButton));
}
}
输出是:
scale 1, location: 296;315
scale 2, location: 296;315
scale 2, location: 346;365
scale 3, location: 346;365
scale 3, location: 396;415
scale 4, location: 396;415
如您所见,存在一个问题,我认为可以使用 Application.DoEvents();< /code> 但是...它在 .NET 4 中先验不存在。
该怎么办?
I have the following sample code that zooms each time a button is pressed:
XAML:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="myCanvas">
<Canvas.LayoutTransform>
<ScaleTransform x:Name="myScaleTransform" />
</Canvas.LayoutTransform>
<Button Content="Button"
Name="myButton"
Canvas.Left="50"
Canvas.Top="50"
Click="myButton_Click" />
</Canvas>
</Window>
*.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
myScaleTransform.ScaleX =
myScaleTransform.ScaleY =
myScaleTransform.ScaleX + 1;
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
}
private Point GetMyByttonLocation()
{
return new Point(
Canvas.GetLeft(myButton),
Canvas.GetTop(myButton));
}
}
the output is:
scale 1, location: 296;315
scale 2, location: 296;315
scale 2, location: 346;365
scale 3, location: 346;365
scale 3, location: 396;415
scale 4, location: 396;415
as you can see, there is a problem, that I thought solve by using Application.DoEvents();
but... it does not exist a priori in .NET 4.
What to do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
尝试这样的事情
Try something like this
好吧,我刚刚遇到一个情况,我开始处理在 Dispatcher 线程上运行的方法,并且它需要阻塞而不阻塞 UI 线程。结果msdn解释了如何基于Dispatcher本身实现DoEvents():(
取自Dispatcher.PushFrame 方法)
有些人可能更喜欢在单个方法中使用它来强制执行相同的逻辑:
另请参阅:https://kent-boogaart.com/blog/dispatcher-frames
Well, I just hit a case where I start work on a method that runs on the Dispatcher thread, and it needs to block without blocking the UI Thread. Turns out that msdn explains how to implement a DoEvents() based on the Dispatcher itself:
(taken from Dispatcher.PushFrame Method)
Some may prefer it in a single method that will enforce the same logic:
See also: https://kent-boogaart.com/blog/dispatcher-frames
旧的 Application.DoEvents() 方法已在 WPF 中弃用,转而使用 调度程序 或 后台工作线程 来执行您所描述的处理。请参阅有关如何使用这两个对象的几篇文章的链接。
如果您绝对必须使用Application.DoEvents(),那么您只需将system.windows.forms.dll 导入您的应用程序并调用该方法即可。但是,确实不建议这样做,因为您将失去 WPF 提供的所有优势。
The old Application.DoEvents() method has been deprecated in WPF in favor of using a Dispatcher or a Background Worker Thread to do the processing as you have described. See the links for a couple of articles on how to use both objects.
If you absolutely must use Application.DoEvents(), then you could simply import the system.windows.forms.dll into your application and call the method. However, this really isn't recommended, since you're losing all the advantages that WPF provides.
如果您只需要更新窗口图形,最好像这样使用
If you need just update window graphic, better use like this
似乎也有效。
seems to work as well.
这两种建议方法的一个问题是它们会导致 CPU 闲置(根据我的经验高达 12%)。在某些情况下,这并不是最理想的,例如使用此技术实现模态 UI 行为时。
以下变体使用计时器引入了帧之间的最小延迟(请注意,此处使用 Rx 编写,但可以使用任何常规计时器来实现):
One problem with both proposed approaches is that they entail idle CPU usage (up to 12% in my experience). This is suboptimal in some cases, for instance when modal UI behavior is implemented using this technique.
The following variation introduces a minimum delay between frames using a timer (note that it is written here with Rx but can be achieved with any regular timer):
自从引入
async
和await
后,现在可以使用Task.Delay
在(以前的)* 同步代码块中途放弃 UI 线程>,例如,说实话,我还没有尝试使用上面的确切代码,但是当我将许多项目放入具有昂贵项目的
ItemsControl
时,我会在紧密循环中使用它模板,有时会添加一点延迟,以便为 UI 上的其他内容提供更多时间。例如:
在Windows Store上,当集合上有一个不错的主题过渡时,效果是相当理想的。
卢克
Since the introduction of
async
andawait
its now possible to relinquish the UI thread partway through a (formerly)* synchronous block of code usingTask.Delay
, e.g.I'll be honest, I've not tried it with the exact code above, but I use it in tight loops when I'm placing many items into an
ItemsControl
which has an expensive item template, sometimes adding a small delay to give the other stuff on the UI more time.For example:
On Windows Store, when there's a nice theme transition on the collection, the effect is quite desirable.
Luke
在 WPF 中创建 DoEvent():
对我来说很好用!
Make your DoEvent() in WPF:
Work well for me!
推入框架:
退出框架:
https://learn.microsoft.com/dotnet/api/ system.windows.threading.dispatcher.pushframe
更新:
使
Task.Delay()
非阻塞的有趣方法Push frame:
Exit frame:
https://learn.microsoft.com/dotnet/api/system.windows.threading.dispatcher.pushframe
Updated:
Interesting way to make
Task.Delay()
non-blocking回答最初的问题:DoEvents 在哪里?
我认为 DoEvents 是 VBA。而且VBA好像没有Sleep功能。但 VBA 有一种方法可以获得与睡眠或延迟完全相同的效果。在我看来,DoEvents 相当于 Sleep(0)。
在 VB 和 C# 中,您正在处理 .NET。而原来的问题是一个C#问题。在 C# 中,您将使用 Thread.Sleep(0),其中 0 表示 0 毫秒。
您需要
在文件顶部才能
在代码中使用。
Answering the original question: Where is DoEvents?
I think DoEvents is VBA. And VBA does not seem to have a Sleep function. But VBA has a way to get exactly the same effect as a Sleep or Delay. Seems to me that DoEvents is equivalent to Sleep(0).
In VB and C#, you are dealing in .NET. And the original question is a C# question. In C#, you would use Thread.Sleep(0), where 0 is 0 milliseconds.
You need
at the top of the file in order to use
in your code.