【问题标题】:System.reactive cross thread operation absurditySystem.reactive 跨线程操作荒谬
【发布时间】:2014-09-04 12:15:10
【问题描述】:

我正在尝试一个非常简单的示例,将订阅的序列输出到文本框以正常工作,正如您所期望的那样,在控制台应用程序中执行此操作没有问题。

我尝试了十几种不同的调用变体,所有这些变体都抛出相同的跨线程嘶嘶声。

我读到 ObserveOnDispatcher 可能会完成这项工作?但我在任何地方都找不到。我试过 ObserveOn,你可以在下面的代码中看到,但同样的问题。

private void button1_Click(object sender, EventArgs e)
{
    var source = Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)).Timestamp();

    source.ObserveOn(Scheduler.CurrentThread).Subscribe(x => textBox1.AppendText(x.Value.ToString()));
}

我不明白为什么以下工作正常;

source.Subscribe(x => MessageBox.Show(x.Value + " - " + x.Timestamp));

然而,将这些值写入文本框需要发脾气。

有什么想法吗?

【问题讨论】:

  • 用 wpf/winforms 标记您的问题
  • 我在 MSDN 论坛上找到了this post,应该可以回答您的问题。
  • 这是无法从工作线程更新控件的类似问题的重复。但是,由于我们不知道您使用的是 WPF 还是 WinForms,因此无法为您指出正确的答案。
  • “这是无法从工作线程更新控件的类似问题的重复” - 虽然不是这样,因为通常调用会起作用,但它不起作用

标签: c# multithreading winforms observablecollection system.reactive


【解决方案1】:

根据 MSDN 论坛上的this answer 使用CurrentThread 调度程序

[...] 并不表示创建查询的线程,它表示正在执行查询的当前线程。在这方面,它类似于即时调度程序。不同之处在于,CurrentThread 调度器对所有调度操作使用单个队列以支持单线程协作多任务,而 Immediate 调度器会立即执行调度操作,而不管先前调度的操作是否仍在执行。

如果您使用 WPF 或 Windows 窗体,可以使用专门的方法来观察 UI 线程:ObserveOnDispatcherObserveOn

【讨论】:

  • 是的,如果您使用 SynchronizationContext.Current,这两种情况都有效,因为如果您在 UI 线程上,这将返回一个特殊版本。
【解决方案2】:

将调度程序传递给Observable.Timer

var source = Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), DispatcherScheduler.Current).Timestamp();

Observable.Timer 默认使用任务池。一般来说,如果操作员允许您指定调度程序,您应该这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    相关资源
    最近更新 更多