Zenject与UniRx结合实现跨线程通信Signal

  •   修改Zenject下ProfileBlock.cs源码, 取消有关UnityEngine.Profiling.Profiler的代码.
  •   然后使用Zenject的Signal:
   // 定义Signal
    public class TestCrossThreadCommEvent : Signal<string, TestCrossThreadCommEvent> { }
View Code
1   // Install Signals
2     Container.DeclareSignal<TestCrossThreadCommEvent>();
View Code
 1 // 启动线程
 2     tth = new Thread(() =>
 3     {
 4         while (true)
 5         {
 6             Thread.Sleep(1000);
 7             _crossThreadCommEvent.Fire("fire not in main thread");
 8             //_unityEvent.Invoke();
 9         }
10     });
11     tth.Start();
12     // UniRx
13     _crossThreadCommEvent.AsObservable.ObserveOnMainThread(MainThreadDispatchType.Update)
14         // 使用lambda表达式是没有问题的
15         .Subscribe(s => TestCrossThreadComm(s))
16         .AddTo(this);
17     
18     void TestCrossThreadComm(string msg)
19     {
20         Debug.Log(Thread.CurrentThread.ManagedThreadId);
21         Debug.Log(msg);
22         transform.RotateAround(transform.position, Vector3.up, 5f);
23     }
View Code
  •  输出结果:
      1
      UnityEngine.Debug:Log(Object)
      fire not in main thread
      UnityEngine.Debug:Log(Object) 
 
  • 多个参数情况:
1 // 定义Signal
2 public class TestCrossThreadCommEvent : Signal<string, string, TestCrossThreadCommEvent> { }
View Code
1 // Install Signals
2 Container.DeclareSignal<TestCrossThreadCommEvent>();
View Code
 1 // 启动线程
 2 tth = new Thread(() =>
 3 {
 4     while (true)
 5     {
 6         Thread.Sleep(1000);
 7         _crossThreadCommEvent.Fire("fire not in main thread", "\t so happy.");
 8         //_unityEvent.Invoke();
 9     }
10 });
11 tth.Start();
12 // UniRx-Lambda
13 _crossThreadCommEvent.AsObservable.ObserveOnMainThread(MainThreadDispatchType.Update)
14     // 使用lambda表达式是没有问题的
15     .Subscribe(tuple =>
16     {
17         Debug.Log(Thread.CurrentThread.ManagedThreadId);
18         Debug.Log(tuple.Item1 + tuple.Item2);
19         transform.RotateAround(transform.position, Vector3.up, 5f);
20     })
21     .AddTo(this);
View Code
  •  输出结果:
1
UnityEngine.Debug:Log(Object)
fire not in main thread     so happy.
UnityEngine.Debug:Log(Object)
 
以上为Asset Store中Zenject早期版本.
目前有版本对Signal部分改动如下:
 1 ...
 2 #if UNITY_EDITOR && ZEN_PROFILING_ENABLED
 3             using (ProfileBlock.Start("Signal '{0}'", this.GetType().Name))
 4 #endif
 5             {
 6                 var wasHandled = Manager.Trigger(SignalId, new object[0]);
 7 
 8                 wasHandled |= (_listeners.Count > 0);
 9 
10                 // Iterate over _tempListeners in case the
11                 // listener removes themselves in the callback
12                 // (we use _tempListeners to avoid memory allocs)
13                 _tempListeners.Clear();
14 
15                 for (int i = 0; i < _listeners.Count; i++)
16                 {
17                     _tempListeners.Add(_listeners[i]);
18                 }
19 
20                 for (int i = 0; i < _tempListeners.Count; i++)
21                 {
22                     var listener = _tempListeners[i];
23 
24 #if UNITY_EDITOR && ZEN_PROFILING_ENABLED
25                     using (ProfileBlock.Start(listener.ToDebugString()))
26 #endif
27                     {
28                         listener();
29                     }
30                 }
31 
32 #if ZEN_SIGNALS_ADD_UNIRX
33                 wasHandled |= _observable.HasObservers;
34 #if UNITY_EDITOR && ZEN_PROFILING_ENABLED
35                 using (ProfileBlock.Start("UniRx Stream"))
36 #endif
37                 {
38                     _observable.OnNext(Unit.Default);
39                 }
40 #endif
41 ...
View Code

涉及到ProfileBlock的使用ZEN_PROFILING_ENABLED来开启, 所以想用Signal跨线程通信,否决掉ZEN_PROFILING_ENABLED就可以了.

posted @ 2017-09-10 13:43  非法关键字  阅读(1413)  评论(0编辑  收藏  举报