zoukankan      html  css  js  c++  java
  • UniRx框架

      之前一些简单功能用 Async await 的写法用的风生水起, 感觉还不错, 不过它的停止功能就比较尴尬, 一个 Task 没有办法去停止, 使用一个 CancelToken 的话还要自己去写里面的逻辑, 非常坑. 有个日本人写了一个整合到 Unity 的叫啥忘了.

      UniRx 其实很早就有人写了, 貌似也是个日本人, 参照的就是微软的 Reactive Extensions, 它也好在异步逻辑可以写成像同步的一样, 不停拼接起来就行了, 比如下面的例子 : 

        var parallel = Observable.WhenAll(
        ObservableWWW.Get("http://google.com/"),
        ObservableWWW.Get("http://bing.com/"),
        ObservableWWW.Get("http://unity3d.com/"));
    
        parallel.Subscribe(xs =>
        {
            Debug.Log(xs[0].Substring(0, 100)); // google
            Debug.Log(xs[1].Substring(0, 100)); // bing
            Debug.Log(xs[2].Substring(0, 100)); // unity
        });

      或者实际使用中的例子, 删掉主要代码后的 : 

        var clearStep = Observable.FromCoroutine(() => ClearIteratively(800));
        List<IObservable<Unit>> allSteps = new List<IObservable<Unit>>() { clearStep };
        foreach(var uploadData in m_points)
        {
            var download = Download(uploadData);
            allSteps.Add(download);
        }
    
        var _Rx = Observable.WhenAll(allSteps.ToArray()).SubscribeOn(Scheduler.ThreadPool).Do<Unit>((_) =>
        {
            // ...
        }).SubscribeOnMainThread().Do<Unit>((_) => { onReceived.Invoke(); }).SelectMany(() => ShowVisualisation(localDatas, Color.red, 100)).Subscribe();

      先做了一个协程的Clear, 然后进行多个数据的下载, 然后所有数据现在完成后在多线程中组装, 之后回到主线程通知, 然后进行协程的显示数据...

      然后最大的好处是我可以在任何时候进行停止逻辑 _Rx.Dispose(); 就行了, 它的执行点在协程的各个 yield 和每个拼接处, 随时都可以进行停止, 或是不再往下执行.

      唯一的问题是一旦进行 Subscribe() 之后, 就无法再在此流程上添加后续处理了, 有点尴尬...

      例子:

            var ob1 = ObservableWWW.Get("https://fanyi.baidu.com/");
    
            var ob2 = Observable.Timer(new System.TimeSpan(0, 0, 5));
    
            var ob3 = ObservableWWW.Get("https://www.baidu.com/");
    
            ob1.Do<string>(x => Debug.Log(x)).ContinueWith(ob2).ContinueWith(ob3).Do<string>(x => Debug.Log(x)).Subscribe();

      如果我是已经开始的一段逻辑:

            var disposable = ob1.Do<string>(x => Debug.Log(x)).ContinueWith(ob2).ContinueWith(ob3).Subscribe();
            // disposable ......

      这时候想要打印 ob3 的内容就没办法了.......

      虽然不完美不过对于异步流水线化的过程来说使用非常方便

    =========== 分割线 ============

      发现这人写的线程转换部分有问题, 不能正确转换线程!!!

        var ob1 = ObservableWWW.Get("https://fanyi.baidu.com/");
        var ob3 = ObservableWWW.Get("https://www.baidu.com/");
        Debug.Log("1 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        // 主线程 -> 子线程 -> 主线程
        Observable.WhenAll(ob1, ob3).SubscribeOn(Scheduler.MainThread).Do((_) =>
        {
            Debug.LogError("2 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }).SubscribeOn(Scheduler.ThreadPool).Do((_) =>
        {
            Debug.LogError("3 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }).SubscribeOnMainThread().Do((_) =>
        {
            Debug.LogError("4 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }).Subscribe();

      

       结果得到个这个, 如果在开始就使用线程, 后面就全是线程了, 转换没有用...

        Debug.Log("1 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        // 主线程 -> 子线程 -> 主线程
        Observable.Start(() =>
        {
            Debug.LogError("2 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }, Scheduler.ThreadPool).Do((_) =>
        {
            Debug.LogError("3 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }).SubscribeOnMainThread().Do((_) =>
        {
            Debug.LogError("4 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }).Subscribe();

      没法用, 自己改起来工程量还挺大的

    ------------------- 再次分割 -----------------------

      看了源码, 原来不是这样用的, 需要调用的接口是 ObserveOn 接口, SubscribeOnMainThread 改为使用 ObserveOnMainThread 即可.......

       Subscrible 在执行链中是反向执行的, 并且在节点上就直接执行了, 比如上面的例子, 倒过来看的话就是先请求进入主线程, 然后再执行了 Observable.Start 进入了工作线程, 之后一直在工作线程里跑.

    ================= 还是分割 ===============

      发现还是不正常 : 

        Debug.Log("1 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        var ob3 = ObservableWWW.Get("https://www.baidu.com/");
        Observable.WhenAll(ob3).ObserveOn(UniRx.Scheduler.ThreadPool).Select((_) =>
        {
            Debug.Log("2 : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
            return 100;
        }).ObserveOn(UniRx.Scheduler.MainThreadEndOfFrame).Do((_) => { Debug.Log("3 : " + System.Threading.Thread.CurrentThread.ManagedThreadId); }).Subscribe();

      运行后LOG只会打印前两个, 后面的执行不到...

       可真是个神奇的东西, 代码懒得看了, 用的烦躁

  • 相关阅读:
    计算一个未排序数组中排序后相邻元素的最大差值
    13 类对象的声明中加小括号{}和不加小括号{}的区别
    12 表中删除重复项
    11 常量区的内容不能被修改
    10 无向图的边
    顺时针旋转矩阵
    字符串的旋转
    动态规划算法
    贪心算法应用-最小生成树
    贪心算法应用-单元最短路径
  • 原文地址:https://www.cnblogs.com/tiancaiwrk/p/15638334.html
Copyright © 2011-2022 走看看