Multithreading 为什么在Task.Run()中更新UI
我正在开发一个Xamarin.Forms应用程序,其中我显示了一个标签,在启动计时器后,它每秒钟更新一次文本。标签的文本值绑定到名为“TimerValue”的ViewModel属性。它用于显示音频输入的录制持续时间。计时器方法如下所示:Multithreading 为什么在Task.Run()中更新UI,multithreading,asynchronous,xamarin.forms,task,threadpool,Multithreading,Asynchronous,Xamarin.forms,Task,Threadpool,我正在开发一个Xamarin.Forms应用程序,其中我显示了一个标签,在启动计时器后,它每秒钟更新一次文本。标签的文本值绑定到名为“TimerValue”的ViewModel属性。它用于显示音频输入的录制持续时间。计时器方法如下所示: /// <summary> /// The start recorder. /// </summary> private void StartTimer() { var st
/// <summary>
/// The start recorder.
/// </summary>
private void StartTimer()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
Device.StartTimer(
new TimeSpan(0, 0, 0, 1, 0),
() =>
{
if (this.isRecording)
{
this.TimerValue = stopwatch.Elapsed.Seconds;
return true;
}
stopwatch.Stop();
this.TimerValue = 0;
return false;
});
}
//
///启动录音机。
///
私有void StartTimer()
{
var stopwatch=新秒表();
秒表。开始();
设备启动程序(
新的时间跨度(0,0,0,1,0),
() =>
{
如果(此.isRecording)
{
this.TimerValue=stopwatch.appeased.Seconds;
返回true;
}
秒表;
this.TimerValue=0;
返回false;
});
}
计时器在任务内启动。在UI事件上调用的运行(GestureRecognizer.Tapped):
wait Task.Run(()=>this.StartTimer()).configurewait(false)代码>
这段代码可以工作,但为什么呢?Run在线程池上启动一个新线程,TimerValue位于UI线程上。在这种情况下,我是否应该调用Xamarin.Forms.Device.BeginInvokeOnMainThread来更新UI
如果我在Task.Run中设置了UI绑定属性,为什么UI会得到更新?Device.StartTimer位于Xamarin.Forms命名空间中。这使得它很可能是一个同步计时器,类似于WPF的Dispatchermer和Winforms的计时器。这使得它非常像是在UI线程上滴答作响。或者永远不要滴答声,你会知道的。这些文件对这件事太模糊了。好吧,这只鞋很合脚。好吧,我以为它在线上滴答滴答地响着它的名字。。。因为如果我不调用Task.Run来启动计时器,如果我切换页面(整个应用程序使用TabbedPage布局来显示其数据),它将停止工作。此外,WPF将允许一些跨线程更新。我不知道Xamarin也会这么做。他们会扔并不意味着他们必须扔。(在我看来,跨线程更新仍然是一个坏主意,即使特定平台实现恰好允许这种更新)。@StephenCleary因此,尽管我的代码在本示例中运行,但您是否建议使用Device.beginInvokeMainThread调用UI线程上的更新?我使用等待获取结果/错误,IProgress
用于进度更新,而SynchronizationContext
用于订阅。看起来您的是订阅模型,所以我会使用SynchronizationContext
.Device.StartTimer位于Xamarin.Forms命名空间中。这使得它很可能是一个同步计时器,类似于WPF的Dispatchermer和Winforms的计时器。这使得它非常像是在UI线程上滴答作响。或者永远不要滴答声,你会知道的。这些文件对这件事太模糊了。好吧,这只鞋很合脚。好吧,我以为它在线上滴答滴答地响着它的名字。。。因为如果我不调用Task.Run来启动计时器,如果我切换页面(整个应用程序使用TabbedPage布局来显示其数据),它将停止工作。此外,WPF将允许一些跨线程更新。我不知道Xamarin也会这么做。他们会扔并不意味着他们必须扔。(在我看来,跨线程更新仍然是一个坏主意,即使特定平台实现恰好允许这种更新)。@StephenCleary因此,尽管我的代码在本示例中运行,但您是否建议使用Device.beginInvokeMainThread调用UI线程上的更新?我使用等待获取结果/错误,IProgress
用于进度更新,而SynchronizationContext
用于订阅。看起来你的是订阅模式,所以我会使用SynchronizationContext
。