nsjsdotnet 在框架中提供了关于 dotnet 协程的实现,它具有完善的 “多协程” 之间的同步,包括类似于“多线程”的“并行计算”库,但协程只是运行于一个物理线程上,而且由于 dotnet 的特性它不可能获取到 C/C++ 上面的效率(基于长条转的原理,它避免了周期性状态机的性能损耗)而 dotnet 是基于事件驱动状态机【EDSM】实现的,它依赖于 dotnet 的迭代器的工作特性,dotnet 可以获取到几乎贴近于 C/C++ 协程的效能,但这需要改进 dotnet/clr 虚拟机才可以。,不过本文的内容建议读者对 “协程” 或者 “多线程” 之间有一定的理解。 (nsjsdotnet sourcecode -> https://github.com/liulilittle/nsjs)
我们为什么需要 “协程”?其原因则是当我们需要大量线程去处理一些不是很重的东西的时候,又需要进行大量的线程之间的阻塞,其对操作系统内核的负载是很重的,但我们借助协程则可以避免这些问题,但协程始终只是运行在单独的一个物理线程(一般会对应到一个具体的CPU核心)那么我们可以把线程阻塞这部分时间省略掉让线程与CPU持续的工作,但就目前多线程的体系架构来说这是很难完成的,但是协程却可以。
你可以为你的应用程序引入 “协程” 它拥有更低的能耗、更好的效率,就大多数网络程序而言其实并不需要应用多线程,单线程的效率是足够应付这些东西,“协程” 可以理解成一个小型的多线程调度系统,只不过两者区别就在于一个是由系统完成一个是由应用程序本身完成。
理解 “协程” 对于理解 “多线程” 是很有帮助的(反过来理解也行),它并不是一个很新鲜的问题,早在多线程提出之前它就已经存在了,或者说 “协程” 就是多线程的前生!
当然 dotnet 并非没有协程的实现,但那种实现是基于 mono 的,所以如果你是想要 “本着不要重复造轮子” 的想法,那么你的确不需要去研发 “协程” 库。
但是 nsjsdotnet 提供的协程库,若你需要运行 “协程” 调度系统,那么你必须指定一个处于运行中的 “物理线程” 用于作为 “协助调度系统”,但当你调用 TaskScheduler::Run 函数运行 “协程” 的调度系统以后,“物理线程” 将被无限的阻塞,用于处理应用系统中 “协程” 之间的调用处理。
namespace TECHMARS.VM
{
using nsjsdotnet.Core.Threading.Coroutines;
using System;
using System.Collections;
using System.Diagnostics;public class Program
{
static IEnumerator Coroutine_Add(int x, int y)
{
yield return x + y;
}static IEnumerator Coroutine_Sub(int x, int y)
{
yield return x - y;
}static IEnumerator Coroutine_Doo()
{
yield return new StackTrace();
}static IEnumerator Coroutine_Main() // 协程入口
{
yield return Task.WaitAny(new[] { Task.Factory.StartNew(Coroutine_Add(1, 2)) }, (index, task) =>
{
Console.WriteLine("CoroutineThreadId: {0}, Coroutine Add Result: {1}", task.Id, task.Result); // 运行一条新的协程
});do
{
Task task = Task.Factory.StartNew(Coroutine_Doo());
yield return Task.WaitAll(new[] { task });
Console.WriteLine("CoroutineThreadId: {0}, Coroutine Doo Result: \n{1}", task.Id, task.Result);
} while (false);do
{
Task task = Task.Factory.StartNew(Coroutine_Sub(3, 1));
yield return Task.WaitAll(new[] { task });
Console.WriteLine("CoroutineThreadId: {0}, Coroutine Sub Result: {1}", task.Id, task.Result);
} while (false);Parallel.For(0, 10, (i) => Console.WriteLine(i + 1)); // 基于协程的并行执行
yield return Task.Sleep(1000); // 睡眠(让出处理器资源)Console.WriteLine("CoroutineThreadId: {0}, ElapsedTick: {1}", Task.Current.Id, Task.Current.Elapsed);
yield return Task.Abort(0); // 中断Console.WriteLine("安全的退出了协程");
}[MTAThread]
static void Main(string[] args)
{
TaskScheduler.Run(Coroutine_Main());
Console.ReadKey();
}
}
}