Просмотр исходного кода

完成Fiber中调用第三方Task,回调到Fiber的功能,这样在Fiber中可以很方便的调用第三方异步方法,跟单线程体验完全一样

tanghai 2 лет назад
Родитель
Сommit
34ab23c941

+ 1 - 6
DotNet/Loader/Init.cs

@@ -6,14 +6,10 @@ namespace ET
 {
 	public class Init
 	{
-		private readonly ThreadSynchronizationContext threadSynchronizationContext = new();
-		
 		public void Start()
 		{
 			try
-			{	
-				SynchronizationContext.SetSynchronizationContext(threadSynchronizationContext);
-				
+			{
 				AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
 				{
 					Log.Error(e.ExceptionObject.ToString());
@@ -35,7 +31,6 @@ namespace ET
 
 		public void Update()
 		{
-			this.threadSynchronizationContext.Update();
 			FiberManager.Instance.Update();
 		}
 

+ 23 - 3
Unity/Assets/Scripts/Core/Fiber/Fiber.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Threading;
 
 namespace ET
 {
@@ -36,6 +37,9 @@ namespace ET
         public TimeInfo TimeInfo { get; }
         public IdGenerater IdGenerater { get; }
         public Mailboxes Mailboxes { get; }
+        public ThreadSynchronizationContext ThreadSynchronizationContext { get; }
+
+        private readonly Queue<ETTask> frameFinishTasks = new();
 
         public bool IsRuning;
         
@@ -48,36 +52,52 @@ namespace ET
             this.TimeInfo = new TimeInfo();
             this.IdGenerater = new IdGenerater(process, this.TimeInfo);
             this.Mailboxes = new Mailboxes();
+            this.ThreadSynchronizationContext = new();
             this.Root = new Scene(this, id, 1, sceneType, name);
         }
 
         public void Update()
         {
             this.IsRuning = true;
-            //this.FiberTaskScheduler.Update();
+            SynchronizationContext.SetSynchronizationContext(this.ThreadSynchronizationContext);
+            this.ThreadSynchronizationContext.Update();
             this.TimeInfo.Update();
             this.EntitySystem.Update();
+            SynchronizationContext.SetSynchronizationContext(null);
         }
         
         public void LateUpdate()
         {
+            SynchronizationContext.SetSynchronizationContext(this.ThreadSynchronizationContext);
             this.EntitySystem.LateUpdate();
             FrameFinishUpdate();
-
+            SynchronizationContext.SetSynchronizationContext(null);
             this.IsRuning = false;
         }
 
         public async ETTask WaitFrameFinish()
         {
-            await ETTask.CompletedTask;
+            ETTask task = ETTask.Create(true);
+            this.frameFinishTasks.Enqueue(task);
+            await task;
         }
 
         private void FrameFinishUpdate()
         {
+            while (this.frameFinishTasks.Count > 0)
+            {
+                ETTask task = this.frameFinishTasks.Dequeue();
+                task.SetResult();
+            }
         }
 
         public void Dispose()
         {
+            if (this.IsDisposed)
+            {
+                return;
+            }
+            this.IsDisposed = true;
             this.Root.Dispose();
         }
     }

+ 14 - 8
Unity/Assets/Scripts/Core/World/Module/Fiber/FiberManager.cs

@@ -19,15 +19,15 @@ namespace ET
         private int idGenerator = 10000000; // 10000000以下为保留的用于StartSceneConfig的fiber id, 1个区配置1000个纤程,可以配置10000个区
         private readonly ConcurrentDictionary<int, Fiber> fibers = new();
 
-        private MainThreadScheduler main;
+        private MainThreadScheduler mainThreadScheduler;
         
         public void Awake()
         {
-            this.main = new MainThreadScheduler(this);
-            this.schedulers[(int)SchedulerType.Main] = this.main;
+            this.mainThreadScheduler = new MainThreadScheduler(this);
+            this.schedulers[(int)SchedulerType.Main] = this.mainThreadScheduler;
             
-            //this.schedulers[(int)SchedulerType.Thread] = this.schedulers[(int)SchedulerType.Main];
-            //this.schedulers[(int)SchedulerType.ThreadPool] = this.schedulers[(int)SchedulerType.Main];
+            //this.schedulers[(int)SchedulerType.Thread] = this.mainThreadScheduler;
+            //this.schedulers[(int)SchedulerType.ThreadPool] = this.mainThreadScheduler;
             
             this.schedulers[(int)SchedulerType.Thread] = new ThreadScheduler(this);
             this.schedulers[(int)SchedulerType.ThreadPool] = new ThreadPoolScheduler(this);
@@ -35,12 +35,12 @@ namespace ET
         
         public void Update()
         {
-            this.main.Update();
+            this.mainThreadScheduler.Update();
         }
 
         public void LateUpdate()
         {
-            this.main.LateUpdate();
+            this.mainThreadScheduler.LateUpdate();
         }
 
         protected override void Destroy()
@@ -61,16 +61,22 @@ namespace ET
             try
             {
                 Fiber fiber = new(fiberId, Options.Instance.Process, zone, sceneType, name);
-            
+
                 fiber.Root.AddComponent<TimerComponent>();
                 fiber.Root.AddComponent<CoroutineLockComponent>();
                 fiber.Root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
                 fiber.Root.AddComponent<ActorSenderComponent>();
                 fiber.Root.AddComponent<ActorRecverComponent>();
             
+                // 这里要换成Fiber的ThreadSynchronizationContext,因为在FiberInit中可能存在调用第三方的Task,需要回调到这个Fiber中来
+                SynchronizationContext old = SynchronizationContext.Current;
+                SynchronizationContext.SetSynchronizationContext(fiber.ThreadSynchronizationContext);
+                
                 // 根据Fiber的SceneType分发Init
                 EventSystem.Instance.Invoke((long)sceneType, new FiberInit() {Fiber = fiber});
                 
+                SynchronizationContext.SetSynchronizationContext(old);
+                
                 this.fibers[fiber.Id] = fiber;
                 
                 this.schedulers[(int) schedulerType].Add(fiberId);

+ 2 - 1
Unity/Assets/Scripts/Core/World/Module/Fiber/MainThreadScheduler.cs

@@ -1,5 +1,6 @@
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Threading;
 
 namespace ET
 {
@@ -42,7 +43,7 @@ namespace ET
                 }
 
                 this.idQueue.Enqueue(id);
-
+                
                 fiber.Update();
             }
         }

+ 4 - 1
Unity/Assets/Scripts/Core/World/Module/Fiber/ThreadScheduler.cs

@@ -19,6 +19,9 @@ namespace ET
 
         private void Loop(int fiberId)
         {
+            Fiber fiber = fiberManager.Get(fiberId);
+            SynchronizationContext.SetSynchronizationContext(fiber.ThreadSynchronizationContext);
+            
             while (true)
             {
                 try
@@ -28,7 +31,7 @@ namespace ET
                         return;
                     }
                     
-                    Fiber fiber = fiberManager.Get(fiberId);
+                    fiber = fiberManager.Get(fiberId);
                     if (fiber == null)
                     {
                         this.dictionary.Remove(fiberId, out _);

+ 1 - 0
Unity/Assets/Scripts/Hotfix/Share/Demo/EntryEvent1_InitShare.cs

@@ -6,6 +6,7 @@ namespace ET
         protected override async ETTask Run(Scene scene, EventType.EntryEvent1 args)
         {
             scene.AddComponent<ObjectWait>();
+            await World.Instance.AddSingleton<ConfigComponent>().LoadAsync();
             await ETTask.CompletedTask;
         }
     }

+ 0 - 6
Unity/Assets/Scripts/Loader/MonoBehaviour/Init.cs

@@ -7,14 +7,10 @@ namespace ET
 {
 	public class Init: MonoBehaviour
 	{
-		private readonly ThreadSynchronizationContext threadSynchronizationContext = new();
-		
 		private void Start()
 		{
 			DontDestroyOnLoad(gameObject);
 			
-			SynchronizationContext.SetSynchronizationContext(threadSynchronizationContext);
-
 			AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
 			{
 				Log.Error(e.ExceptionObject.ToString());
@@ -34,13 +30,11 @@ namespace ET
 
 		private void Update()
 		{
-			threadSynchronizationContext.Update();
 			FiberManager.Instance.Update();
 		}
 
 		private void LateUpdate()
 		{
-			threadSynchronizationContext.Update();
 			FiberManager.Instance.LateUpdate();
 		}
 

+ 2 - 3
Unity/Assets/Scripts/Model/Share/Entry.cs

@@ -51,10 +51,9 @@ namespace ET
             World.Instance.AddSingleton<NavmeshComponent>();
             
             World.Instance.AddSingleton<FiberManager>();
-            
-            await World.Instance.AddSingleton<ConfigComponent>().LoadAsync();
-            
             FiberManager.Instance.Create(SchedulerType.Main, ConstFiberId.Main, 0, SceneType.Main, "");
+            
+            await ETTask.CompletedTask;
         }
     }
 }