ET介绍——CSharp协程
什么是协程
说到协程,我们先了解什么是异步,异步简单说来就是,我要发起一个调用,但是这个被调用方(可能是其它线程,也可能是IO)出结果需要一段时间,我不想让这个调用阻塞住调用方的整个线程,因此传给被调用方一个回调函数,被调用方运行完成后回调这个回调函数就能通知调用方继续往下执行。举个例子:
下面的代码,主线程一直循环,每循环一次sleep 1毫秒,计数加一,每10000次打印一次。
private static void Main()
{
int loopCount = 0;
while (true)
{
int temp = watcherValue; Thread.Sleep(1); ++loopCount;
if (loopCount % 10000 == 0)
{
Console.WriteLine($"loop count: {loopCount}");
}
}
}
这时我需要加个功能,在程序一开始,我希望在5秒钟之后打印出loopCount的值。看到5秒后我们可以想到Sleep方法,它会阻塞线程一定时间然后继续执行。我们显然不能在主线程中Sleep,因为会破坏掉每10000次计数打印一次的逻辑。
// example2_1
class Program
{
private static int loopCount = 0; private static void Main()
{
OneThreadSynchronizationContext _ = OneThreadSynchronizationContext.Instance; WaitTimeAsync(5000, WaitTimeFinishCallback); while (true)
{
OneThreadSynchronizationContext.Instance.Update(); Thread.Sleep(1); ++loopCount;
if (loopCount % 10000 == 0)
{
Console.WriteLine($"loop count: {loopCount}");
}
}
} private static void WaitTimeAsync(int waitTime, Action action)
{
Thread thread = new Thread(()=>WaitTime(waitTime, action));
thread.Start();
} private static void WaitTimeFinishCallback()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
} /// <summary>
/// 在另外的线程等待
/// </summary>
private static void WaitTime(int waitTime, Action action)
{
Thread.Sleep(waitTime); // 将action扔回主线程执行
OneThreadSynchronizationContext.Instance.Post((o)=>action(), null);
}
}
我们在这里设计了一个WaitTimeAsync方法,WaitTimeAsync其实就是一个典型的异步方法,它从主线程发起调用,传入了一个WaitTimeFinishCallback回调方法做参数,开启了一个线程,线程Sleep一定时间后,将传过来的回调扔回到主线程执行。OneThreadSynchronizationContext是一个跨线程队列,任何线程可以往里面扔委托,OneThreadSynchronizationContext的Update方法在主线程中调用,会将这些委托取出来放到主线程执行。为什么回调方法需要扔回到主线程执行呢?因为回调方法中读取了loopCount,loopCount在主线程中也有读写,所以要么加锁,要么永远保证只在主线程中读写。加锁是个不好的做法,代码中到处是锁会导致阅读跟维护困难,很容易产生多线程bug。这种将逻辑打包成委托然后扔回另外一个线程是多线程开发中常用的技巧。
我们可能又有个新需求,WaitTimeFinishCallback执行完成之后,再想等3秒,再打印一下loopCount。
private static void WaitTimeAsync(int waitTime, Action action)
{
Thread thread = new Thread(()=>WaitTime(waitTime, action));
thread.Start();
}
private static void WaitTimeFinishCallback()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
WaitTimeAsync(3000, WaitTimeFinishCallback2);
} private static void WaitTimeFinishCallback2()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
}
我们这时还可能改需求,需要在程序启动5秒后,接下来4秒,再接下来3秒,打印loopCount,也就是上面的逻辑中间再插入一个3秒等待。
private static void WaitTimeAsync(int waitTime, Action action)
{
Thread thread = new Thread(()=>WaitTime(waitTime, action));
thread.Start();
} private static void WaitTimeFinishCallback()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
WaitTimeAsync(4000, WaitTimeFinishCallback3);
} private static void WaitTimeFinishCallback3()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
WaitTimeAsync(3000, WaitTimeFinishCallback2);
} private static void WaitTimeFinishCallback2()
{
Console.WriteLine($"WaitTimeAsync finsih loopCount的值是: {loopCount}");
}
这样中间插入一段代码,显得非常麻烦。这里可以回答什么是协程了,其实这一串串回调就是协程。
ET开源地址地址:egametang/ET: Unity3D Client And C# Server Framework (github.com) qq群:474643097
ET介绍——CSharp协程的更多相关文章
- Lua的协程和协程库详解
我们首先介绍一下什么是协程.然后详细介绍一下coroutine库,然后介绍一下协程的简单用法,最后介绍一下协程的复杂用法. 一.协程是什么? (1)线程 首先复习一下多线程.我们都知道线程——Thre ...
- [转载]协程-cooperative multitasking
[转载]协程三讲 http://ravenw.com/blog/2011/08/24/coroutine-part-1-defination-and-classification-of-corouti ...
- coroutine协程
如果你接触过lua这种小巧的脚本语言,你就会经常接触到一个叫做协程的神奇概念.大多数脚本语言都有对协程不同程度的支持.但是大多编译语言,如C/C++,根本就不知道这样的东西存在.当然也很多人研究如何在 ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- Python协程(真才实学,想学的进来)
真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒. --蒙田<蒙田随笔全集> *** 上篇论述了关 ...
- 异步时代-java的协程路在何方
面试官:你知道协程吗? 你:订机票的那个吗,我常用. 面试官:行,你先回去吧,到时候电话联系 ........ 很尴尬,但是事实是,很大一部分的程序员不知道协程是啥玩意,更大一部分的程序员,项目中没用 ...
- python基础(16)-进程&线程&协程
进程之multiprocessing模块 Process(进程) Process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建. 介绍 初始化参数 Process([group [, t ...
- (转)python协程2:yield from 从入门到精通
原文:http://blog.gusibi.com/post/python-coroutine-yield-from/ https://mp.weixin.qq.com/s?__biz=MzAwNjI ...
- Python并发编程系列之协程
1 引言 协程是近几年并发编程的一个热门话题,与Python多进程.多线程相比,协程在很多方面优势明显.本文从协程的定义和意义出发,结合asyncio模块详细讲述协程的使用. 2 协程的意义 2.1 ...
- 协程,纤程(Fiber),或者绿色线程(GreenThread)
纤程(Fiber),或者绿色线程(GreenThread) 面试官:你知道协程吗? 你:订机票的那个吗,我常用. 面试官:行,你先回去吧,到时候电话联系 ........ 很尴尬,但是事实是,很大一部 ...
随机推荐
- KCP协议浅析
概述 KCP协议结合了TCP和UDP协议的特点,是一个快速可靠的协议. 引述官方介绍: KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大 ...
- CMSGC-GCRoots-三色标记
CMS收集器的特点:追求最短的停顿时间. CMS-Concurrent Mark Sweep 并发 标记 清除 标记垃圾的方式 标记清除:标记处需要回收的对象,标记完成后统一回收所有被标记的对象. 标 ...
- CSS实现文字颜色渐变效果
略微搜索查阅了网上的实现方法: 1.给元素添加背景渐变色,通过背景裁剪其中文字,再将文字设置为透明即可实现.(兼容性问题请自行添加浏览器前缀) background-color:linear-grad ...
- Mybatis应用手册
重学mybatis框架,汇成应用手册,整理mybatis中用法且附相关实例,方便日常回顾 目录结构: ----------------- Github手册地址:https://github.com/x ...
- active
rabbitMQ与activeMQ区别 之前的项目中都用到了这两个消息队列 ActiveMq,传统的消息队列,使用Java语言编写.基于JMS(Java Message Service),采用多线程并 ...
- 有了HTTP,为啥还要用RPC
既然有 HTTP 请求,为什么还要用 RPC 调用? 一直以来都没有深究过RPC和HTTP的区别,不都是写一个服务然后在客户端调用么? HTTP和RPC最本质的区别,就是 RPC 主要是基于 TCP/ ...
- Flutter 下载篇 - 叁 | 网络库切换实践与思考
前言 本文是关于使用flutter_download_manager下载功能的实践和探索.我们将基于flutter_download_manager的功能扩展,改造成自己想要的样子.在阅读本文之前,建 ...
- 商品获价API调用说明:获取商品历史价格信息 代码分享
接口名称:item_history_price 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中)(获取测试key和secret接入) secre ...
- 如何通过Java代码将添加页码到PDF文档?
页码可以清楚了解总页数.定位页数快速寻找自己所要的文段.打印时不会分不清头中尾.很多人在使用办公软件的时候就会选择PDF进行文档的保存,因为PDF在保存之后不会出现乱码甚至是格式改变的情况.在PDF中 ...
- 迁移学习(SPI)《Semi-Supervised Domain Adaptation by Similarity based Pseudo-label Injection》
论文信息 论文标题:Semi-Supervised Domain Adaptation by Similarity based Pseudo-label Injection论文作者:Abhay Raw ...