.net4.0使用yield避免异步操作大量回调嵌套

  在.net4.0以上版本,提供了async、await关键词,可以很好的解决异步操作代码顺序问题,可以像写同步代码一样顺序编写代码,非常容易阅读。但.net4.0中的异步还是要依赖回调,代码嵌套层次过多,看代码的时候容易晕。

  比如软件中有一个工作线程,接收工作任务,任务执行完毕后,通知调用方,调用方继续下发任务,这些任务顺序执行,组合起来完成一个功能。

//工作线程对象

private Thread _workThread = null; 

//工作任务队列

private List<tuple<string, action>> _taskList = new List<tuple<string, action>>(); 

//启动工作线程

private void button3_Click(object sender, EventArgs e) 

    _workThread = new Thread(new ThreadStart(() => { 

        while (true) 

        {

             if (_taskList.Count > 0) 

            { 

                var task = _taskList[0]; 

               _taskList.RemoveAt(0);

               task.Item4(string.Format("{0}_{1}_{2}", task.Item1, task.Item2, task.Item3)); 

               Thread.Sleep(5000); 

           } 

          else

         { 

              Thread.Sleep(20); 

         } 

       } 

      })); 

    _workThread.IsBackground = true; 

    _workThread.Start(); 

//传统方式 很多嵌套回调

private void button4_Click(object sender, EventArgs e) 

    //注册第一个异步 

    _taskList.Add(new Tuple<string, action>(DateTime.Now.ToString(), 1, 1, new Action((str1) => { 

        Debug.WriteLine(str1); 

        //第一个异步执行完毕,在注册第二个异步 

        _taskList.Add(new Tuple<string, action>(DateTime.Now.ToString(), 1, 1, new Action((str2) => { Debug.WriteLine(str2); 

        //...继续注册下去,很多嵌套层 

        })));

     })));

 } 

//改进方式:

    IEnumerator _call = null; 

    private IEnumerable Execute() 

    { 

        string value = string.Empty; 

        var callback = new Action((str) => { 

            value = str; 

            Debug.WriteLine(DateTime.Now.ToString() + " callback run"); 

           _call.MoveNext(); 

        });

         //触发工作线程工作,并退出执行,等待下一次调用MoveNext

        //即给工作线程一个动作,工作线程执行完动作后,调用_call.MoveNext()函数,这样主线程的foreach语句就行执行下一次循环了。

       _taskList.Add(new Tuple<string, action>(DateTime.Now.ToString(), 0, 0, callback)); 

        yield return 0;

         _taskList.Add(new Tuple<string, action>(DateTime.Now.ToString(), 1, 1, callback)); 

        yield return 1; 

        //工作线程根据回调函数通知请求执行完毕 

        Debug.WriteLine(DateTime.Now.ToString() + " over"); 

        yield return 2;

 } 

private void button5_Click(object sender, EventArgs e) 

    _call = Execute().GetEnumerator(); 

   _call.MoveNext(); 

改进方式还是要依赖工作线程执行完毕的回调通知,但在写业务逻辑的时候,避免了大量回调嵌套,代码可读性得到改善。

由于具体任务是在子线程中执行的,UI界面保持正常刷新。

yield如果不跨线程执行,感觉也没有什么作用,只是一个语法糖,提供了创建IEnumerable对象的方案而已,变通一下还是可以改进代码质量的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值