【问题标题】:DispatcherTimer in MVVM with Prism?带有Prism的MVVM中的DispatcherTimer?
【发布时间】:2019-04-05 19:26:30
【问题描述】:

我正在开发一个多平台 MVVM 应用程序,我希望保持 ViewModel 平台不可知。

我需要使用DispatcherTimer 或任何其他计时器。由于DispatcherTimer 不是.NET Standard/Core 的一部分,我想知道是否有更好的替代方案可以使用,这样我就可以保持VM 中没有特定于平台的代码(我希望它只依赖于.NET Core)?

它的工作方式是 ViewModel 实现一个接口,该接口公开 View 正在侦听的事件,并相应地响应它。
计时器在每次滴答时引发此事件。

【问题讨论】:

  • 您需要在 UI 线程上运行上述代码吗?
  • @MartinZikmund 我已经更新了我的问题。
  • 为什么需要视图模型在 UI 线程上引发事件?为什么不在视图级别使用 UI 线程?你的应用定位是什么?如果您的目标是 Prism.UWP,那么您可以使用 DispatcherTimer。如果你想让视图模型跨平台,你可以使用库的消费者必须实现的接口——比如IDispatcher和方法RunOnUiThread(Action action)

标签: mvvm timer uwp .net-core prism


【解决方案1】:

第一个选项是只使用经典的Timer,它会在非 UI 线程上触发,然后在消费视图中手动使用 Dispatcher。然而,这并不那么方便。

其他选项是提供一个接口,您的库的使用者可以实现该接口,该接口将具有类似 RunOnUiThread(Action action) 的方法,您可以使用它来确保特定于视图的代码在 UI 线程上运行。

最好的解决方案可能是从Prism 本身获得灵感。例如库中的EventAggregator 可以在UI 线程上发布事件——它首先捕获当前线程的同步上下文(参见here on GitHub):

var syncContext = SynchronizationContext.Current;

这必须在例如视图模型构建期间在 UI 线程上完成。然后您甚至可以从另一个线程调用此 UI 同步上下文的操作(请参阅here on GitHub):

syncContext.Post((o) => action(), null);

这样,您可以只使用 .NET Standard Timer classes 之一,然后从它们的回调中使用 SynchronizationContext 在 UI 线程上运行操作。

【讨论】:

  • 感谢您的全面回答。我想我会选择 EventAggregator 并使用 .NET Standard Timer 类来引发 Prism 事件。
  • 是的,如果您已经在使用 Prism,事件聚合器是一个很好的解决方案。没有重新发明轮子:-)
【解决方案2】:

关于 DispatcherTimer 您应该了解的另一种方式是有时我们可能会使用 DispatcherTimer 交替执行某些操作。

我们有时可以使用Task.Delay 来替换DispatcherTimer。

比如我们需要每5秒运行一次代码A。

   public async void Foo()
    {
        while (true)
        {
            // run a every 5 seconds
            await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5));
            A();
        }
    }

    private void A()
    {

    }

如果主线程调用 Foo,A 将在主线程中运行,我认为你 可以考虑在框架中使用这种方法。

【讨论】:

  • 这种方式恐怕时间不够准确。但最好注意参考。
猜你喜欢
  • 2011-08-14
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
  • 2012-07-29
  • 2011-10-06
  • 1970-01-01
  • 2011-02-06
相关资源
最近更新 更多