diff --git a/Server/Model/Server.Model.csproj b/Server/Model/Server.Model.csproj
index 1839cf167045beea9cff38bab5e7af8488107057..9f8dbdfb226301a304637e9f36629afdcc2127ba 100644
--- a/Server/Model/Server.Model.csproj
+++ b/Server/Model/Server.Model.csproj
@@ -26,6 +26,9 @@
Base\Async\AsyncETVoidMethodBuilder.cs
+
+ Base\Async\ETCancellationTokenSource.cs
+
Base\Async\ETTask.cs
diff --git a/Unity/Assets/Model/Base/Async/ETCancellationTokenSource.cs b/Unity/Assets/Model/Base/Async/ETCancellationTokenSource.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5abc837c1b0bfcbb617f85015c543cf69975a42c
--- /dev/null
+++ b/Unity/Assets/Model/Base/Async/ETCancellationTokenSource.cs
@@ -0,0 +1,78 @@
+using System.Threading;
+
+namespace ETModel
+{
+ [ObjectSystem]
+ public class ETCancellationTokenSourceAwakeSystem: AwakeSystem
+ {
+ public override void Awake(ETCancellationTokenSource self)
+ {
+ self.CancellationTokenSource = new CancellationTokenSource();
+ }
+ }
+
+ [ObjectSystem]
+ public class ETCancellationTokenSourceAwake2System: AwakeSystem
+ {
+ public override void Awake(ETCancellationTokenSource self, long afterTimeCancel)
+ {
+ self.CancellationTokenSource = new CancellationTokenSource();
+ self.CancelAfter(afterTimeCancel).Coroutine();
+ }
+ }
+
+ public class ETCancellationTokenSource: Component
+ {
+ public CancellationTokenSource CancellationTokenSource;
+
+ public void Cancel()
+ {
+ if (this.CancellationTokenSource == null)
+ {
+ return;
+ }
+ CancellationTokenSource cts = this.CancellationTokenSource;
+ this.CancellationTokenSource = null;
+ cts?.Cancel();
+ }
+
+ public async ETVoid CancelAfter(long afterTimeCancel)
+ {
+ if (this.CancellationTokenSource == null)
+ {
+ return;
+ }
+
+ await Game.Scene.GetComponent().WaitAsync(afterTimeCancel);
+
+ if (this.CancellationTokenSource == null)
+ {
+ return;
+ }
+
+ CancellationTokenSource cts = this.CancellationTokenSource;
+ this.CancellationTokenSource = null;
+ cts?.Cancel();
+ }
+
+ public CancellationToken Token
+ {
+ get
+ {
+ return this.CancellationTokenSource.Token;
+ }
+ }
+
+ public override void Dispose()
+ {
+ if (this.IsDisposed)
+ {
+ return;
+ }
+
+ base.Dispose();
+
+ this.CancellationTokenSource?.Cancel();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Unity/Unity.Model.csproj b/Unity/Unity.Model.csproj
index f3f259d2d1164db3b6aabab27fe89a02309829b0..aa7232c29a4dc2f3c41cd0405d42a0739b98b8a3 100644
--- a/Unity/Unity.Model.csproj
+++ b/Unity/Unity.Model.csproj
@@ -57,6 +57,7 @@
+