单线程异步

前面几个例子都是多线程实现的异步,但是异步显然不仅仅是多线程的。我们在之前的例子中使用了Sleep来实现时间的等待,每一个计时器都需要使用一个线程,会导致线程切换频繁,这个实现效率很低,平常是不会这样做的。一般游戏逻辑中会设计一个单线程的计时器,我们这里做一个简单的实现,用来讲解单线程异步。

    // example2_3
class Program
{
private static int loopCount = 0; private static long time;
private static Action action; static void Main(string[] args)
{
Console.WriteLine($"主线程: {Thread.CurrentThread.ManagedThreadId}"); Crontine(); while (true)
{
Thread.Sleep(1); CheckTimerOut(); ++loopCount;
if (loopCount % 10000 == 0)
{
Console.WriteLine($"loop count: {loopCount}");
}
}
} private static void Crontine()
{
WaitTimeAsync(5000, WaitTimeAsyncCallback1);
} private static void WaitTimeAsyncCallback1()
{
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
WaitTimeAsync(4000, WaitTimeAsyncCallback2);
} private static void WaitTimeAsyncCallback2()
{
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
WaitTimeAsync(3000, WaitTimeAsyncCallback3);
} private static void WaitTimeAsyncCallback3()
{
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
} private static void CheckTimerOut()
{
if (time == 0)
{
return;
}
long nowTicks = DateTime.Now.Ticks / 10000;
if (time > nowTicks)
{
return;
} time = 0;
action.Invoke();
} private static void WaitTimeAsync(int waitTime, Action a)
{
time = DateTime.Now.Ticks / 10000 + waitTime;
action = a;
}
}

这个例子同样实现了一个简单的计时方法,WaitTimeAsync调用时会将回调方法跟时间记录下来,主线程每帧都会调用CheckTimerOut,CheckTimerOut里面判断计时器是否过期,过期了则调用回调方法。整个逻辑都在主线程中完成,同样是异步方法。所以异步并非多线程,单线程同样可以异步。上面的例子同样可以改成await的形式。

    // example2_3_2
class Program
{
private static int loopCount = 0; private static long time;
private static TaskCompletionSource<bool> tcs; static void Main(string[] args)
{
Console.WriteLine($"主线程: {Thread.CurrentThread.ManagedThreadId}"); Crontine(); while (true)
{
Thread.Sleep(1); CheckTimerOut(); ++loopCount;
if (loopCount % 10000 == 0)
{
Console.WriteLine($"loop count: {loopCount}");
}
}
} private static async void Crontine()
{
await WaitTimeAsync(5000);
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
await WaitTimeAsync(4000);
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
await WaitTimeAsync(3000);
Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
} private static void CheckTimerOut()
{
if (time == 0)
{
return;
}
long nowTicks = DateTime.Now.Ticks / 10000;
if (time > nowTicks)
{
return;
} time = 0;
tcs.SetResult(true);
} private static Task WaitTimeAsync(int waitTime)
{
TaskCompletionSource<bool> t = new TaskCompletionSource<bool>();
time = DateTime.Now.Ticks / 10000 + waitTime;
tcs = t;
return t.Task;
}
}

上面这个例子所有调用全部在主线程中完成,并且使用了await,因此await并不会开启多线程,await具体用没用多线程完全取决于具体的实现

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

ET介绍——单线程异步的更多相关文章

  1. 【Python】迭代器、生成器、yield单线程异步并发实现详解

    转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...

  2. tornado原理介绍及异步非阻塞实现方式

    tornado原理介绍及异步非阻塞实现方式 以下内容根据自己实操和理解进行的整理,欢迎交流~ 在tornado的开发中,我们一般会见到以下四个组成部分. ioloop: 同一个ioloop实例运行在一 ...

  3. JS定时器和单线程异步特性

    首先要说的是,定时器相关的方法都是属于BOM方法,而定时器呢,它是用于在设定的时间执行一段代码,或者在给定的时间间隔内重复该代码.具体函数: setTimeout(callback, delay);/ ...

  4. 单线程异步回调机制的缺陷与node的解决方案

    一.node单线程异步的缺陷: 单线程异步的优点自然不必多说,node之所以能够如此快的兴起,其单线程异步回调机制相比于传统同步执行编程语言的优势便是原因之一.然而,开发一个node程序,其缺陷也是不 ...

  5. node 单线程异步非阻塞

    链接:http://www.runoob.com/nodejs/nodejs-callback.html 首先什么是单线程异步非阻塞? 单线程的意思整个程序从头到尾但是运用一个线程,程序是从上往下执行 ...

  6. js 单线程 异步

    线程与进程: 进程是系统资源分配和调度的单元.一个运行着的程序就对应一个进程.在windows中,每一个打开的运行的应用程序或后台程序,比如运行中的qq,谷歌浏览器,网易云音乐,资源管理器等都是一个进 ...

  7. 爬虫基础--IO多路复用单线程异步非阻塞

    最近一直的学习爬虫  ,进行基础的学习 性能相关 参考 https://www.cnblogs.com/wupeiqi/p/6229292.html # 目标:单线程实现并发HTTP请求 # # so ...

  8. android:异步任务asyncTask介绍及异步任务下载图片(带进度条)

    为什么要用异步任务? 在android中仅仅有在主线程才干对ui进行更新操作.而其他线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把全部的操作都放在主线程中操作 .比方 ...

  9. Python网络编程中的服务器架构(负载均衡、单线程、多线程和同步、异步等)

    这篇文章主要介绍服务器架构. 网络服务需要面对两个挑战. 第一个问题是核心挑战,要编写出能够正确处理请求并构造合适响应的代码. 第二个挑战是如何将网络代码部署到随系统自动启动的Windows服务或者是 ...

  10. 重回博客 谈一谈Node中的异步和单线程

    重回博客,这个帐号之前注册后就只发了一篇博客.听朋友建议,决定一周两次更新. 第一篇谈论一下最近想的比较多的异步的问题. 传统多线程异步 传统的异步是多线程的,当要同时做两件事的时候,他们是执行在不同 ...

随机推荐

  1. go build gcc报错 /usr/bin/ld | cannot find -ldl cannot find -lpthread cannot find -lc

    之前一直在kali或者其他ubuntu设备编译sliver, 临时在centos7上编译时报错了 # github.com/bishopfox/sliver/server /usr/local/go/ ...

  2. win32 - 从dll中导出api并使用

    从User32.dll中导出MessageBoxW 代码: #include <Windows.h> #include <iostream> #include <func ...

  3. 项目实战:医疗流式细胞术数据文件(.fcs)导出excel表工具

    需求    解析医疗实验室数据文件*.fcs.   Demo导出数据   医疗流式细胞术数据文件标准(.fcs)   流式细胞术数据文件标准于1984年发布,以促进流式细胞术数据分析软件与在不同类型的 ...

  4. Qt三方库开发技术(一):QuaZIP介绍、编译和使用

    前言   Qt使用一些压缩解压功能,探讨过libzip库,zlib库,libzip库比较原始,还有其他库,都比较基础,而在基础库之上,又有高级封装库,Qt中的QuaZIP是一个很好的选择.  本文主要 ...

  5. locals()用法

    views.py代码 def test(request): if request.method == 'GET': return render(request,'test.html') elif re ...

  6. python内置模块argparse的使用

    官网文档 https://docs.python.org/3/howto/argparse.html # 简易教程 https://docs.python.org/3/library/argparse ...

  7. SpringBoot面试题的零碎整理

    面试题1:简述一下Springboot相对SSM做了哪些提升? 首先,SpringBoot是采用"约定大于配置"(Convention over Configuration)的理念 ...

  8. C++异常的基本概念与用法

    //异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try{}内写可能会抛出异常的代码.catch(类型){处理} 写异常类型和异常处理 抛出 ...

  9. Java 重写引入

    1 package com.bytezero.override; 2 /* 3 * 方法的重新(override/overwrite) 4 * 5 * 1.重写:子类继承父类以后,可以对父类中同名同参 ...

  10. 【规范】看看人家Git提交描述,那叫一个规矩

    前言 缘由 没想到玩了多年git,竟然还有提交描述规范 事情起因: 在工作迭代过程中,偶然发现同组小帅哥Git提交描述总是和自己的不大一样,秉承好奇至上的我特意去研究了下.竟然发现提交了这么多年的Gi ...