UWP 从 Task 更新 UI

Posted

技术标签:

【中文标题】UWP 从 Task 更新 UI【英文标题】:UWP update UI from Task 【发布时间】:2016-11-04 02:57:00 【问题描述】:

我有一个应用程序,它正在检查本地网络中的网络范围(用于运行 http 服务)。

所以这意味着,我正在检查 f.e.从 10.0.0.1 到 10.0.0.255。问题来了,在 PC 上运行时速度足够,但在 Lumia 950 上运行时速度不够。所以我想在扫描期间更新 UI。

以下是问题:

    此时我有几个任务 f.e. 10 - 每个任务都在扫描他的范围 f.e.任务 1 - 10.0.0.1 到 10.0.0.25 等 - 我应该使用 10 个任务还是有什么方法,.net 将如何自行解决?表现如何,f.e.如果我将使用 50 个任务?

    第二个问题是,在扫描过程中,我会找到正在运行 Web 服务的 PC,但是……当找到 PC 时,我应该如何更新 UI?目前我只能在所有任务完成后才能做到..

我调用的方法是异步任务

【问题讨论】:

【参考方案1】:

    您可以使用任意数量的任务,系统会自动为您进行排队和执行。这是使用内置机制的优势之一

    要在 UI 线程上执行代码,您可以像这样使用调度程序:

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => 
                //UI code here
    );
    

【讨论】:

您好,感谢您的回答.. 它似乎正在工作.. 但还有一些其他要求...例如,如果一个线程会找到服务器,我应该将它添加到 ListBox,是有什么办法可以解决吗? 很高兴听到这有帮助。您可以考虑将此标记为答案,以便其他人轻松发现。对于另一个要求,这应该是一个单独的问题。尝试并提供一些您尝试过的示例代码,以便人们知道从哪里开始提供答案。 Dispatcher 没有 RunAsync 方法? 如何防止出现:“名称调度程序在当前上下文中不存在”? 你应该写 Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () = > );【参考方案2】:

要在 UI 线程上执行代码并且您只想更新属性。您可以使用 MVVM 和 ViewModel 继承类

public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged

   public event PropertyChangedEventHandler PropertyChanged;

   protected async void OnPropertyChanged([CallerMemberName] string propName = "")
   
       await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.High,
           () =>
           
               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
           );
   

Xaml 绑定的所有属性都使用单向或双向,并且在属性中使用 OnPropertyChanged();如果时间我的代码异常并说Current is null

你可以使用

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 

     //write your code
     //in OnPropertyChanged use PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
);

如果您在用户控件或页面中编写了代码,您可以看到以下代码。

await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => 

            //UI code here
);

CoreDispatcherPriority 可以设置 Priority 但您不应该将其设置为 High ,请参阅CoreDispatcherPriority

【讨论】:

你好,看起来很有趣,我部分使用了你的方式。但问题是,从类中更新 GUI 是否好?我不认为它是干净的..也许还有另一种解决方案? 如果你绑定,它已经更新。有一些,我没有链接。 所以最后我使用了这个解决方案,它工作了link 如果你改变了属性,而你的UI没有改变。所以最后你也应该像我一样使用代码。链接(c-sharpcorner.com/UploadFile/5ef5aa/…)可以更改列表但不能更改属性。 使用 ObservableCollection 它可以在项目添加或删除时通知。【参考方案3】:

我还发现了另一种更新 UI 的可能性——此时我正在通过这种方式更新进度条,但发现你可以传递其他变量..

 var progress = new Progress<int>(i => _progress = i);
 progress.ProgressChanged += Pr_ProgressChanged;

然后事件:

  private void Pr_ProgressChanged(object sender, int e)
    
        progressBar1.Value = progressBar1.Value + 1;
    

带参数的方法:

 public async Task GetWebServers(IProgress<int> progress) 
 //your code

调用:

await Task.WhenAll(workers.Select(webServer => webServer.GetWebServers(progress))
       );

【讨论】:

这在某些情况下可以工作,但要从异步任务调用 UI(可以从其他线程调用),最好使用 Dispatcher。

以上是关于UWP 从 Task 更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

UWP Xaml文本块数据绑定 - 即使属性已更新,UI也不会更新

如何更新 UWP Microsoft Toolkit DataGrid 中的单元格值?

使用Task来实现跨线程更新UI

C#UWP UI调度程序优化(Windows IoT核心)

从后台任务中更新android UI

从 JavaFX 中的不同线程更新 UI