【问题标题】:ObserveOnDispatcher dose not invoke the handler in UI threadObserveOnDispatcher 不会在 UI 线程中调用处理程序
【发布时间】:2015-12-10 12:08:19
【问题描述】:

我有一个消息总线类,它使用 Rx 在 WPF 应用程序中推送多个线程事件。 我的问题 ObserveOnDispatcher 没有在 UI 线程中调用事件处理程序。

代码:

private void button_Click(object sender, RoutedEventArgs e)
{
  var messageBus = new MessageBus();
  messageBus.GetMessages<Message>().ObserveOnDispatcher().Subscribe(x => TestHanlder(x));

  Trace.WriteLine("Main Thread Id:" + Thread.CurrentThread.ManagedThreadId);
  var deviceManager = new DeviceManager(messageBus);
  deviceManager.Start();
}

private void TestHanlder(Message message)
{
  Trace.WriteLine("UI Handler ThreadId:" + Thread.CurrentThread.ManagedThreadId);
}

public class DeviceManager
{
  private readonly MessageBus _messageBus;

  public DeviceManager(MessageBus messageBus)
  {
    _messageBus = messageBus;
  }

  public void Start()
  {
    for (;;)
    {
      var t = Task.Factory.StartNew(() => BackGroundTask(), TaskCreationOptions.LongRunning);
      t.Wait();
    }
  }

  private void BackGroundTask()
  {
    Thread.Sleep(1000);
    Trace.WriteLine("Push ThreadId:" + Thread.CurrentThread.ManagedThreadId);
    var message = new Message();
    _messageBus.Publish(message);
  }
}

public class MessageBus
{
  readonly ISubject<object> _messages;

  public MessageBus()
  {
    _messages = new Subject<object>();
  }
  public void Publish<TMessage>(TMessage message)
  {
    _messages.OnNext(message);
  }

  public IObservable<TMessage> GetMessages<TMessage>()
  {
    return _messages.OfType<TMessage>();
  }
}

public class Message
{
  public Message()
  {

  }
}

Without ObserveOnDispatcher:
messageBus.GetMessages<Message>().Subscribe(x => TestHanlder(x));
..........................Output.................................
Main Thread Id:8
Push ThreadId:9
UI Handler ThreadId:9
But I need to execute the TestHanlder function in the main thread or UI thread, in my use case above it must be the thread number 8.

When I use ObserveOnDispatcher:
messageBus.GetMessages<Message>().ObserveOnDispatcher().Subscribe(x => TestHanlder(x));
..........................Output.................................

Main Thread Id:9
Push ThreadId:10
 ------------------> UI Handler ThreadId: are missing not there!?
What I'm doing wrong here?!!!!!

【问题讨论】:

  • 我的代码有什么问题?非常感谢任何帮助...
  • 有很多“MessageBus”类。如果它在工作线程上产生消息,并非不可能,那么 ObserveOnDispatcher() 将使用错误的调度程序。
  • @HansPassant 好点我也认为 ObserveOnDispatcher 使用了错误的调度程序,但我如何证明这一点?我应该为 MessageBus 类使用其他实现吗?

标签: c# wpf system.reactive reactiveui message-bus


【解决方案1】:

for (;;) { t.Wait(); } 此代码在 UI 线程中执行,并阻止它执行在其上调度的任何其他内容。 ObserveOnDispatcher 工作正常,但您的调度程序线程被阻塞。

如果您引入 async/await(这将释放线程),该场景将正常工作:

    private async void button_Click(object sender, RoutedEventArgs e)
    {
        var messageBus = new MessageBus();
        messageBus.GetMessages<Message>().ObserveOnDispatcher().Subscribe(x => TestHanlder(x));

        Trace.WriteLine("Main Thread Id:" + Thread.CurrentThread.ManagedThreadId);
        var deviceManager = new DeviceManager(messageBus);
        await deviceManager.Start();
    }

    ...

        public async Task<Unit> Start()
        {
            for (;;)
            {
                await Task.Factory.StartNew(() => BackGroundTask(), TaskCreationOptions.LongRunning);
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2020-02-03
    • 2020-10-09
    • 2015-10-27
    • 1970-01-01
    相关资源
    最近更新 更多