首页 > 解决方案 > 在 UWP、MVVM 中实现周期性进程

问题描述

我正在构建一个从网站收集数据的小型应用程序。我设法收集了数据。

下图描述了我的应用程序的功能。

在此处输入图像描述

当我单击“시작”按钮时,我的应用程序会获取特定页面的 html,并从中获取数据。这项工作在 ViewModel 类中完成,我将结果数据绑定到 ViewPage,观察我认为的 mvvm 模式。

以下源代码显示了我为程序编写的逻辑。

public class MainPageViewModel : Observable
{

    public SiseDataList dataList { get; set; } = new SiseDataList();

    public MainPageViewModel()
    {
         ButtonClick = new RelayCommand(Click);
    }

    public async void Click()
    {
        // ... omitted .. 
        foreach (var i in tmp_list) 
        {
            if (dataList.Count == 0)
            {
                dataList.Add(i);
            }
            else if (dataList.Last().date < i.date)
            {
                dataList.Add(i);
            }
        }

        OnPropertyChanged("data");
    }
    public RelayCommand ButtonClick { get; set; }
}

我将data_list数据绑定到viewPage, GridView

现在,我想我可以说出我想要实现的内容了。

如果我点击我的应用程序的“시작”按钮,我想每 20 秒执行一次点击功能。

幸运的是,我可以很容易地找到关于 UWP 中定期工作的文档。链接:创建定期工作项

因此,我尝试实现该功能,但失败了。
首先,我尝试了以下方法:

public MainPageViewModel()
{
     ButtonClick = new RelayCommand(Regist);
}

public async void Regist()
{
    TimeSpan period = TimeSpan.FromSeconds(60);

    ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (source) =>
    {
        Dispatcher.RunAsync(CoreDispatcherPriority.High,
            () =>
            {
                // UI components can be accessed within this scope.
                Click();
            });

    }, period);

}

public async void Click() //...omitted.. 

我把Click()函数放在里面Dispatcher,因为我认为函数是从接口Click()调用的。但 Intellisense 告诉我,它在上下文中 找不到任何名称。 所以我只是右键单击它并单击重构菜单,然后,那句话变成了 但是它不起作用。我在文档中找到了类,所以我使用了它。我写了,但它不是一个静态类,我不能使用那种语法。 OnPropertyChanged()INotifyPropertyChanged
Dispatcher
System.ServiceModel.Dispatcher.RunAsync...
CoreDispatcherCoreDispatcher.RunAsync(....)

我用谷歌搜索并尝试过Window.Current.Dispatcher.RunAsync(....),但它返回异常“ Windows.UI.Xaml.Windows.Current.getreturns null”。

最后,我尝试了以下代码。

 TimeSpan period = TimeSpan.FromSeconds(60);

 ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer((source) =>
 {
     Click();
 }, period);

但是程序在执行ClickdataList 列表中的添加元素时崩溃了,我认为其他线程(一种 UI 线程......?)在我将它绑定到查看页面时正在观看或持有该列表。它返回异常“来自 HRESULT 的异常:0x8001010E (RPC_E_WRONG_THREAD)”。

如何在 UWP 中定期执行特定功能?

标签: c#mvvmuwpscheduled-tasks

解决方案


您需要使用Dispatcher应用程序(与主窗口的调度程序匹配):

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
        CoreDispatcherPriority.High,
        () =>
        {
            // UI components can be accessed within this scope.
            Click();
        });

您的方法不起作用的原因是无法Window.Current.Dispatcher从非 UI 线程调用,因为Window.Current只能在 UI 线程上访问。但是Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher可以从任何地方访问。


推荐阅读