需要Observable计时器将消息传递给UI线程

时间:2014-01-27 20:09:12

标签: c# system.reactive

此代码,从UI线程调用:

Jobs.Current.ShowProgress(_ =>
    {
        if (Jobs.Current.Duration == 0 && this.progressBarMarkJob.Value >= this.progressBarMarkJob.Maximum - this.progressBarMarkJob.Step / 2)
        {
            this.progressBarMarkJob.Step /= 2;
        }
        this.progressBarMarkJob.PerformStep();
    }, () =>
    {
        stopwatch.Stop();
        var elapsed = string.Format(stopwatch.Elapsed.TotalHours >= 1 ? @"{0:hh\:mm\:SS}" : @"{0:mm\:SS}", stopwatch.Elapsed);
        this.labelMarkTime.Text = string.Format("Elapsed{0:8}", elapsed);
        this.labelMarkTime.Visible = true;
        Jobs.Current.Duration = (uint)stopwatch.Elapsed.TotalSeconds;
        this.progressBarMarkJob.Value = this.progressBarMarkJob.Maximum;
    });

ShowProgress在哪里:

public void ShowProgress(Action<long> notify, Action terminate)
{
    this.Progress = Observable.Timer(ProgressInterval, ProgressInterval).Finally(terminate).Subscribe(notify);
}

完全阻止UI线程,使其无响应。

如果我在Subscribe()调用之前插入.SubscribeOn(Scheduler.CurrentThread),它将不再阻止UI线程。但后来我得到了跨线程异常,因为消息没有传递给正确线程上的UI。

有没有办法使这项工作能够让我从定时器获得更新 - 让UI响应 - 发回到UI线程?

1 个答案:

答案 0 :(得分:2)

您需要添加对ObserveOn()的通话。如果您使用nuget包Rx-Xaml,您可以利用ObserveOnDispatcher():

this.Progress = Observable.Interval(ProgressInterval)
                          .ObserveOnDispatcher()
                          .Finally(terminate)
                          .Subscribe(notify);

See my answer here to understand the difference between ObserveOn and SubscribeOn。此外,您不提供PerformStep()的代码 - 我希望它快速和/或无阻塞。

我还将Timer替换为Interval,因为它可以为您节省一个参数。

最后,大概是你计划在作业完成时处理订阅句柄(this.Progress)?