经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
ET介绍——CSharp协程
来源:cnblogs  作者:Flamesky  时间:2023/5/19 9:10:49  对本文有异议

什么是协程

说到协程,我们先了解什么是异步,异步简单说来就是,我要发起一个调用,但是这个被调用方(可能是其它线程,也可能是IO)出结果需要一段时间,我不想让这个调用阻塞住调用方的整个线程,因此传给被调用方一个回调函数,被调用方运行完成后回调这个回调函数就能通知调用方继续往下执行。举个例子:
下面的代码,主线程一直循环,每循环一次sleep 1毫秒,计数加一,每10000次打印一次。

  1. private static void Main()
  2. {
  3. int loopCount = 0;
  4. while (true)
  5. {
  6. int temp = watcherValue;
  7. Thread.Sleep(1);
  8. ++loopCount;
  9. if (loopCount % 10000 == 0)
  10. {
  11. Console.WriteLine($"loop count: {loopCount}");
  12. }
  13. }
  14. }

 

这时我需要加个功能,在程序一开始,我希望在5秒钟之后打印出loopCount的值。看到5秒后我们可以想到Sleep方法,它会阻塞线程一定时间然后继续执行。我们显然不能在主线程中Sleep,因为会破坏掉每10000次计数打印一次的逻辑。

  1. // example2_1
  2. class Program
  3. {
  4. private static int loopCount = 0;
  5. private static void Main()
  6. {
  7. OneThreadSynchronizationContext _ = OneThreadSynchronizationContext.Instance;
  8. WaitTimeAsync(5000, WaitTimeFinishCallback);
  9. while (true)
  10. {
  11. OneThreadSynchronizationContext.Instance.Update();
  12. Thread.Sleep(1);
  13. ++loopCount;
  14. if (loopCount % 10000 == 0)
  15. {
  16. Console.WriteLine($"loop count: {loopCount}");
  17. }
  18. }
  19. }
  20. private static void WaitTimeAsync(int waitTime, Action action)
  21. {
  22. Thread thread = new Thread(()=>WaitTime(waitTime, action));
  23. thread.Start();
  24. }
  25. private static void WaitTimeFinishCallback()
  26. {
  27. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  28. }
  29. /// <summary>
  30. /// 在另外的线程等待
  31. /// </summary>
  32. private static void WaitTime(int waitTime, Action action)
  33. {
  34. Thread.Sleep(waitTime);
  35. // 将action扔回主线程执行
  36. OneThreadSynchronizationContext.Instance.Post((o)=>action(), null);
  37. }
  38. }

 

我们在这里设计了一个WaitTimeAsync方法,WaitTimeAsync其实就是一个典型的异步方法,它从主线程发起调用,传入了一个WaitTimeFinishCallback回调方法做参数,开启了一个线程,线程Sleep一定时间后,将传过来的回调扔回到主线程执行。OneThreadSynchronizationContext是一个跨线程队列,任何线程可以往里面扔委托,OneThreadSynchronizationContext的Update方法在主线程中调用,会将这些委托取出来放到主线程执行。为什么回调方法需要扔回到主线程执行呢?因为回调方法中读取了loopCount,loopCount在主线程中也有读写,所以要么加锁,要么永远保证只在主线程中读写。加锁是个不好的做法,代码中到处是锁会导致阅读跟维护困难,很容易产生多线程bug。这种将逻辑打包成委托然后扔回另外一个线程是多线程开发中常用的技巧。

我们可能又有个新需求,WaitTimeFinishCallback执行完成之后,再想等3秒,再打印一下loopCount。

  1. private static void WaitTimeAsync(int waitTime, Action action)
  2. {
  3. Thread thread = new Thread(()=>WaitTime(waitTime, action));
  4. thread.Start();
  5. }
  6. private static void WaitTimeFinishCallback()
  7. {
  8. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  9. WaitTimeAsync(3000, WaitTimeFinishCallback2);
  10. }
  11. private static void WaitTimeFinishCallback2()
  12. {
  13. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  14. }

 

我们这时还可能改需求,需要在程序启动5秒后,接下来4秒,再接下来3秒,打印loopCount,也就是上面的逻辑中间再插入一个3秒等待。

  1. private static void WaitTimeAsync(int waitTime, Action action)
  2. {
  3. Thread thread = new Thread(()=>WaitTime(waitTime, action));
  4. thread.Start();
  5. }
  6. private static void WaitTimeFinishCallback()
  7. {
  8. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  9. WaitTimeAsync(4000, WaitTimeFinishCallback3);
  10. }
  11. private static void WaitTimeFinishCallback3()
  12. {
  13. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  14. WaitTimeAsync(3000, WaitTimeFinishCallback2);
  15. }
  16. private static void WaitTimeFinishCallback2()
  17. {
  18. Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
  19. }

 

这样中间插入一段代码,显得非常麻烦。这里可以回答什么是协程了,其实这一串串回调就是协程。

ET开源地址地址:egametang/ET: Unity3D Client And C# Server Framework (github.com)   qq群:474643097

原文链接:https://www.cnblogs.com/flamesky/p/17413661.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号