首先,经过深思熟虑,我认为我没有正确地提出这个标题。
但是,我一直在尝试从Task.Run(async()=> {})表达式/方法中生成的多个线程中找到更新UI控件的方法。我在UWP windows mobile 10应用程序中这样做。
我已经列出了大部分涉及的例程,并且需要帮助完成对DisplayProgress(字符串消息)方法的调用。在这个方法中,我想使用Dispathcer.RunAsync()以线程安全的方式更新UI控件,但需要它是线程安全的。请参阅以下代码中的尝试1& 2 。
void printMessage(int value) {
System.out.println("Your score is " + score);
}
我发现了这篇文章http://briandunnington.github.io/uitask.html,但是,我不确定这种方法是正确的还是线程安全的。对于应该由Dispatacher.RunAsync()处理的东西,似乎有很多样板代码?我读过的其他文章指向Action代理,我认为它应该是线程安全的,但经过几次(非常详细的技术文章)之后,我现在感到困惑。其他文章:Are C# delegates thread-safe?(不幸的是,我只能链接到2篇文章 - 需要先提高我的积分!)
答案 0 :(得分:3)
我不确定这种方法是正确的还是线程安全的。看起来像Dispatacher.RunAsync()应该处理的很多样板代码?
You can access the UI element safely使用其Dispatcher属性,或者UI线程上下文中存在的任何对象的Dispatcher属性(,例如按钮所在的页面)。
在UI线程上创建的Windows运行时对象的生命周期受线程生命周期的限制。窗口关闭后,不要尝试访问UI线程上的对象。
以下是对Microsoft github repository的正式建议。
通常,您可以通过调用Dispatcher.RunAsync(CoreDispatcherPriority.Normal,()=> / *更新UI * /)从后台线程更新UI。但是,这仅仅调度UI线程上的工作并立即返回,即使任务是等待弹出框中的用户输入。它也没有为任务提供将结果返回给调用者的方法。
RunTaskAsync提供了一个替代方法,它将TaskCompletionSource与RunAsync结合使用,以返回一个可以从后台线程中等待的Task,从而暂停执行,直到UI任务完成。
因为RunTaskAsync是一个扩展方法,所以你将它称为Dispatcher上的方法:var result = await Dispatcher.RunTaskAsync(async()=> {...; return value;});
using System;
using System.Threading.Tasks;
using Windows.UI.Core;
public static class DispatcherTaskExtensions
{
public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
{
var taskCompletionSource = new TaskCompletionSource<T>();
await dispatcher.RunAsync(priority, async () =>
{
try
{
taskCompletionSource.SetResult(await func());
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
return await taskCompletionSource.Task;
}
// There is no TaskCompletionSource<void> so we use a bool that we throw away.
public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
}
是否有必要锁定多个线程通过调度程序访问同一个uwp组件的代码段?
您不必添加锁。 Dispatcher.RunTaskAsync请求不会在其他代码的中间运行(这就是它们的全部内容)。
答案 1 :(得分:0)
这解决了这个问题:
.as-console-wrapper { max-height: 100%!important; top: 0; }
修订后的代码
private async Task DisplayProgess(string message)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lsvInvSynchProgress.Items.Add($"{message} - {DateTime.Now}");
});
}