WPF中的Application.DoEvents()在哪里?

ser*_*hio 82 .net c# wpf xaml

我有以下示例代码,每次按下按钮时缩放:

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>
Run Code Online (Sandbox Code Playgroud)

*的.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));
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

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
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,有一个问题,我认为通过使用Application.DoEvents();但是......它在.NET 4 中不存在先验.

该怎么办?

Fre*_*lad 129

尝试这样的事情

public static void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
                                          new Action(delegate { }));
}
Run Code Online (Sandbox Code Playgroud)

  • 这并不总是有效,因为它不会推送帧,如果正在执行中断指令(即调用 WCF 方法,该方法以同步方式继续执行此命令)您将看不到“刷新”,因为它将被阻止.. 这就是为什么从 MSDN 资源提供的答案 flq 比这个更正确。 (5认同)
  • 我什至为应用程序编写了一个扩展方法:) `public static void DoEvents(this Application a)` (2认同)
  • 但是我应该注意到,在实际的应用程序中,`Application.Current`有时候是空的...所以也许它不完全相同. (2认同)

flq*_*flq 55

好吧,我刚刚开始研究一个在Dispatcher线程上运行的方法,并且需要在不阻塞UI线程的情况下阻塞.事实证明,msdn解释了如何基于Dispatcher本身实现DoEvents():

public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}

public object ExitFrame(object f)
{
    ((DispatcherFrame)f).Continue = false;

    return null;
}
Run Code Online (Sandbox Code Playgroud)

(取自Dispatcher.PushFrame方法)

  • @HugoRune 那篇博文指出这种方法是不必要的,并且使用与 Meleak 相同的实现。 (2认同)

Dil*_*e-O 25

在WPF中不推荐使用旧的Application.DoEvents()方法,而是使用Dispatcher后台工作线程来执行您所描述的处理.有关如何使用这两个对象的文章,请参阅链接.

如果您绝对必须使用Application.DoEvents(),那么您只需将system.windows.forms.dll导入您的应用程序并调用该方法即可.但是,这不建议使用,因为您正在失去WPF提供的所有优势.

  • 删除Application.DoEvents()几乎和MS删除Windows 8上的"开始"按钮一样烦人. (10认同)
  • 调用WinForms的DoEvents将无法正常工作. (6认同)
  • 我了解你的情况.当我编写我的第一个WPF应用程序时,我就在其中,但是我继续花时间学习新的库,从长远来看,它更好.我强烈建议你抽空.至于你的特殊情况,它看起来像你希望调度员每次点击事件触发时都处理坐标的显示.您需要在Dispatcher上阅读更多内容以了解具体实现方法. (3认同)
  • 不,这是一件好事,这种方法造成的伤害大于好处. (2认同)
  • 我不敢相信这在当今时代仍然是一个问题。我记得必须在 VB6 中调用 DoEvents 来模拟异步行为。问题是,后台工作人员仅在您不执行 UI 处理时才工作,但 UI 处理 - 例如创建数千个 ListBoxItems 可能会锁定 UI 线程。当确实有大量的 UI 工作要做时,我们应该做什么? (2认同)

小智 10

如果您只需要更新窗口图形,最好像这样使用

public static void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Render,
                                          new Action(delegate { }));
}
Run Code Online (Sandbox Code Playgroud)


ser*_*hio 6

myCanvas.UpdateLayout();
Run Code Online (Sandbox Code Playgroud)

似乎也运作良好.