如何在Xamarin.Forms中实现异步计时器

时间:2017-05-16 17:59:21

标签: c# asynchronous xamarin xamarin.forms

我正在用Xamarin.Forms实现录音机。应该有一个显示记录器运行时间的计时器。在点击图像时,录制开始,如果用户再次点击,则录制停止。点击的命令代码如下所示:

    /// <summary>
    ///     The on tabbed command.
    /// </summary>
    private async void OnTappedCommand()
    {
        if (this.isRecording)
        {
            this.isRecording = false;
            await this.StopRecording().ConfigureAwait(false); // Stops the MediaRecorder
        }
        else
        {
            this.isRecording = true;
            await this.StartTimer().ConfigureAwait(false); // Starts the Timer
            await this.StartRecording().ConfigureAwait(false); // Starts the MediaRecorder
        }
    }

StartTimer()方法如下所示:

private async Task StartTimer()
    {
        Device.StartTimer(
            new TimeSpan(0, 0, 0, 0, 1),
            () =>
                {
                    if (this.isRecording)
                    {
                        Device.BeginInvokeOnMainThread(
                            () =>
                                {
                                    this.TimerValue = this.TimerValue + 1;
                                });

                        return true;
                    }

                    Device.BeginInvokeOnMainThread(
                        () =>
                            {
                                this.TimerValue = 0;
                            });

                    return false;
                });
}

TimerValue 是绑定到标签的简单整数属性,该标签使用ValueConverter来处理格式。

我的问题是:

1。即使我删除了Device.BeginInvokeOnMainThread方法,为什么我的代码也能正常工作?它不应该抛出错误,因为它没有在UI-Thread上运行并尝试更新UI-Bound TimerValue属性,因为使用了ConfigureAwait(false)?

2。你在哪里建议在这段代码中使用Task.Run(),或者根本不应该使用它?

1 个答案:

答案 0 :(得分:0)

1-之所以起作用,是因为计时器将在 UI线程(主线程)中运行代码。 与Device.BeginInvokeOnMainThread()使用的相同。 当您的代码用完 UI线程(请参阅下一个答案)

时,可以使用它

2-在您的示例中完全不应使用它,因为this.TimerValue是由 UI线程创建的(并且是其属性) Task.Run()在“线程池”中执行代码,并且无法触摸由“ UI线程”创建的对象。 “线程池”将用于较长的作业,并且不应与UI交互。