【问题标题】:How do I "DoEvents" in WPF?如何在 WPF 中“DoEvents”?
【发布时间】:2010-04-19 12:33:48
【问题描述】:

我看过C#版本如下:

Application.Current.Dispatcher.Invoke(
          DispatcherPriority.Background,
          new Action(delegate { }));

但是我不知道如何将空委托放入 VB.NET,因为 VB.NET 似乎不支持匿名方法。想法?

编辑:可能是这个?

Application.Current.Dispatcher.Invoke(
  DispatcherPriority.Background,
  New Action(Sub()

             End Sub))

【问题讨论】:

  • DoEvents?我相信他们曾经在 VB6 中使用过 DoEvents,然后人们才意识到应用程序可以拥有的不仅仅是 UI 线程。
  • 现代约定是使用 Thread.Sleep(1) 或类似的,但是当您需要临时跳出线程以允许 UI 更新自身并保留在WPF 中处理循环的中间。
  • @SLC:如果您在另一个线程中进行处理,那么您不需要告诉 UI 进行自我更新(以一般刷新的方式)。
  • 您必须中断 UI 线程以通知它更新进度条,这在使用 Invoke 方法的 Windows 窗体中是可能的,但我相信它在 WPF 中有所不同,这就是使用此方法的原因。 . 但老实说,我对 WPF 一无所知,只是将 C# 转换为 VB。
  • 我的应用程序中有一个地方。问题是 Thread.Sleep(1) 和 Thread.Join() 也阻塞了 Dispatcher 队列。在我的应用程序中,我有一个完成大量工作的第二个线程。在 Application-Exit 事件期间,我关闭了该线程并等待它完成。但是,由于该线程还涉及一些 UI 对象,因此 Dispatcher 队列必须保持活动状态。因此,需要 DoEvents。

标签: wpf vb.net


【解决方案1】:

VB.NET 确实支持匿名委托,但仅作为单语句函数。 (VB10在.NET 4中添加了多语句匿名函数和匿名Subs)

为了提供上下文,DoEvents 旨在允许单线程环境在工作完成时更新 UI 并处理其他 Windows 消息。从另一个线程调用DoEvents(或者,正如您在这里所做的那样,通过在调度程序上执行“null”函数间接这样做)应该没有任何好处,因为 UI 线程应该自行更新。

不过,为了回答您的问题,最简单的选择是这样的:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, _
    New Action(Function() 7))

但是,再一次,我看不出这实际上会完成什么。

如果您正在寻找的只是如何在 UI 线程上执行代码(如 Windows 窗体中的 Control.Invoke),那么 Dispatcher.Invoke(您正在使用的)是正确的,您将只需将您的内联匿名方法转换为谨慎的函数并将它们作为委托传递。可能有一些你可以匿名离开。例如,如果您所做的只是更新进度条,您可以这样做:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, _
    New Action(Function() progressBar.Value = 100))

这是可行的,因为所有赋值都返回存储在赋值左侧的值。但是,您不能只调用这样的子程序(除非SomeFunctionName 返回值,否则以下代码不会编译):

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, _
    New Action(Function() SomeFunctionName(params)))

换句话说,C# 代码中的任何匿名委托:

  • 不止一个陈述
  • 不返回值(意味着它只是对方法的一次调用,而不是函数)

然后您必须为这些函数创建函数并将委托传递给这些函数,而不是像在 C# 中那样内联代码。

【讨论】:

  • UI 只能在有机会的情况下更新,也就是在函数的末尾。这就是为什么如果您将循环放入应用程序会变得无响应的原因,即使使用线程睡眠也不会在循环中更新 UI 组件,而无需在 Windows 窗体中执行 Invoke 以强制切换到另一个线程。我推测这是一样的。
  • 您可以将 Function() 更改为 Sub() 并且只有一个空的 Sub() 正如我在编辑中推测的那样,因为我刚刚在代码中确认它并且它似乎有效。
  • @SLC:仅当您正在执行的操作发生在 UI 线程上 时,这才是正确的。如果代码在另一个线程上执行,那么这不是必需的。 如果您正在执行的操作在 UI 线程上执行,并且花费的时间足以需要显式更新 UI,那么应该将其移至另一个线程。
  • @SLC:Sub 选项仅适用于 VB10 (VisualStudio 2010/.NET 4)。
  • Robinson - 将操作移动到另一个线程并不总是可行的。例如,在您从序列化的 XAML 表单加载 FlowDocument 的情况下,您无法在 BG 线程上生成它,然后在 UI 线程上显示它。它必须在 UI 线程上创建和加载。
【解决方案2】:

如果您想在 UI 上刷新某些内容,您可以简单地调用此方法:

System.Windows.Forms.Application.DoEvents

我们在 WPF Window 和 XBAP 应用程序中使用它。

【讨论】:

    【解决方案3】:

    这里有两个问题,所以我要添加两个答案。在这里,我正在回答“如何在 WPF 中执行 DoEvents”。 Bea Stollnitz 在her blog 上对此进行了介绍,这是 VB 中的代码:

    publicShared Sub WaitForPriority(priority As DispatcherPriority)
        Dim frame As New DispatcherFrame()
        Dim dispatcherOperation As DispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(priority, New DispatcherOperationCallback(ExitFrameOperation), frame)
        Dispatcher.PushFrame(frame)
        If dispatcherOperation.Status <> DispatcherOperationStatus.Completed Then
            dispatcherOperation.Abort()
        End If
    End Sub
    
    Private Shared Function ExitFrameOperation(obj As Object) As Object
        (DirectCast(obj, DispatcherFrame)).[Continue] = False
        Return Nothing
    End Function
    

    【讨论】:

      【解决方案4】:

      或简单地使用调度程序为 WPF 制作一个 Doevents():

          'The WPF equivalent of DoEvents!!
      Public Sub DoEvents()
          Dispatcher.Invoke(New Action(Function()
                                           Return Nothing
                                       End Function), DispatcherPriority.ContextIdle, Nothing)
      End Sub
      

      【讨论】:

        【解决方案5】:

        使用 Function 关键字:

        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, New Action(Function() Do ... End Function))
        

        【讨论】:

        • 问题是动作什么都不做,那么我可以在里面放什么“什么都没有”?还有一个函数返回一个变量。
        • 如果你只是删除点,它会编译吗?我们在这里讨论的是哪个版本的 VB / .NET?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-11
        相关资源
        最近更新 更多