diff --git a/src/DevTools/PerformanceImpact-Async-Fork/App.config b/src/DevTools/PerformanceImpact-Async-Fork/App.config
new file mode 100644
index 00000000..bae5d6d8
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Fork/App.config
@@ -0,0 +1,6 @@
+
+
+     
+        
+    
+
diff --git a/src/DevTools/PerformanceImpact-Async-Fork/PerformanceImpact-Async-Fork.csproj b/src/DevTools/PerformanceImpact-Async-Fork/PerformanceImpact-Async-Fork.csproj
new file mode 100644
index 00000000..708a3c26
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Fork/PerformanceImpact-Async-Fork.csproj
@@ -0,0 +1,64 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {F7E4153A-B2DA-47D0-BE67-DABC54DB6670}
+    Exe
+    PerformanceImpact_Async_Fork
+    PerformanceImpact_Async_Fork
+    v4.6.1
+    512
+    true
+    true
+    
+    
+  
+  
+    AnyCPU
+    true
+    full
+    false
+    bin\Debug\
+    TRACE;DEBUG;FORK
+    prompt
+    4
+    false
+  
+  
+    AnyCPU
+    pdbonly
+    true
+    bin\Release\
+    TRACE;FORK
+    prompt
+    4
+    false
+  
+  
+    
+    
+    
+    
+    
+    
+    
+    
+  
+  
+    
+    
+  
+  
+    
+    
+  
+  
+    
+      {49f32476-fca0-45fd-8f89-0c7c0d15e409}
+      MoonSharp.Interpreter.portable40
+    
+  
+  
+
\ No newline at end of file
diff --git a/src/DevTools/PerformanceImpact-Async-Fork/Program.cs b/src/DevTools/PerformanceImpact-Async-Fork/Program.cs
new file mode 100644
index 00000000..9ea4936f
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Fork/Program.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Diagnostics;
+
+namespace PerformanceImpact_Async
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            var code = @"
+			function move(n, src, dst, via)
+				if n > 0 then
+					move(n - 1, src, via, dst)
+					--check(src, 'to', dst)
+					move(n - 1, via, dst, src)
+				end
+			end
+ 
+            function run_test()
+			    for i = 1, 15000 do
+				    move(4, 1, 2, 3)
+			    end
+            end
+			";
+
+            Script.WarmUp();
+
+            var S = new Script();
+
+            S.DoString(code);
+
+            long totalTime = 0;
+            long i = 0;
+
+            var run_testFunc = S.Globals.Get("run_test");
+
+#if FORK
+            var ecToken = new ExecutionControlToken();
+#endif
+
+            while (true)
+            {
+                S.PerformanceStats.Enabled = true;
+
+#if FORK
+                S.CallAsync(ecToken, run_testFunc).Wait();
+#else
+                S.CallAsync(run_testFunc).Wait();
+#endif
+
+                // Get current average
+                totalTime += S.PerformanceStats.GetPerformanceCounterResult(PerformanceCounter.Execution).Counter;
+
+                ++i;
+
+                Console.WriteLine("Current average: {0}", totalTime / i);
+
+                //Thread.Sleep(20);
+
+                S.PerformanceStats.Enabled = false;
+            }
+        }
+    }
+}
diff --git a/src/DevTools/PerformanceImpact-Async-Fork/Properties/AssemblyInfo.cs b/src/DevTools/PerformanceImpact-Async-Fork/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..b15694a2
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Fork/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PerformanceImpact-Async-Original")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PerformanceImpact-Async-Original")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a7a642d3-2efa-4eaa-9762-6dc9e0c883a1")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/DevTools/PerformanceImpact-Async-Fork/packages.config b/src/DevTools/PerformanceImpact-Async-Fork/packages.config
new file mode 100644
index 00000000..52a7d804
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Fork/packages.config
@@ -0,0 +1,4 @@
+
+
+  
+
\ No newline at end of file
diff --git a/src/DevTools/PerformanceImpact-Async-Original/App.config b/src/DevTools/PerformanceImpact-Async-Original/App.config
new file mode 100644
index 00000000..bae5d6d8
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Original/App.config
@@ -0,0 +1,6 @@
+
+
+     
+        
+    
+
diff --git a/src/DevTools/PerformanceImpact-Async-Original/PerformanceImpact-Async-Original.csproj b/src/DevTools/PerformanceImpact-Async-Original/PerformanceImpact-Async-Original.csproj
new file mode 100644
index 00000000..4efbb193
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Original/PerformanceImpact-Async-Original.csproj
@@ -0,0 +1,61 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {A7A642D3-2EFA-4EAA-9762-6DC9E0C883A1}
+    Exe
+    PerformanceImpact_Async_Original
+    PerformanceImpact_Async_Original
+    v4.6.1
+    512
+    true
+    true
+    
+    
+  
+  
+    AnyCPU
+    true
+    full
+    false
+    bin\Debug\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    AnyCPU
+    pdbonly
+    true
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      ..\..\packages\MoonSharp.2.0.0.0\lib\net40-client\MoonSharp.Interpreter.dll
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+  
+    
+    
+  
+  
+    
+    
+  
+  
+
\ No newline at end of file
diff --git a/src/DevTools/PerformanceImpact-Async-Original/Program.cs b/src/DevTools/PerformanceImpact-Async-Original/Program.cs
new file mode 100644
index 00000000..9ea4936f
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Original/Program.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Diagnostics;
+
+namespace PerformanceImpact_Async
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            var code = @"
+			function move(n, src, dst, via)
+				if n > 0 then
+					move(n - 1, src, via, dst)
+					--check(src, 'to', dst)
+					move(n - 1, via, dst, src)
+				end
+			end
+ 
+            function run_test()
+			    for i = 1, 15000 do
+				    move(4, 1, 2, 3)
+			    end
+            end
+			";
+
+            Script.WarmUp();
+
+            var S = new Script();
+
+            S.DoString(code);
+
+            long totalTime = 0;
+            long i = 0;
+
+            var run_testFunc = S.Globals.Get("run_test");
+
+#if FORK
+            var ecToken = new ExecutionControlToken();
+#endif
+
+            while (true)
+            {
+                S.PerformanceStats.Enabled = true;
+
+#if FORK
+                S.CallAsync(ecToken, run_testFunc).Wait();
+#else
+                S.CallAsync(run_testFunc).Wait();
+#endif
+
+                // Get current average
+                totalTime += S.PerformanceStats.GetPerformanceCounterResult(PerformanceCounter.Execution).Counter;
+
+                ++i;
+
+                Console.WriteLine("Current average: {0}", totalTime / i);
+
+                //Thread.Sleep(20);
+
+                S.PerformanceStats.Enabled = false;
+            }
+        }
+    }
+}
diff --git a/src/DevTools/PerformanceImpact-Async-Original/Properties/AssemblyInfo.cs b/src/DevTools/PerformanceImpact-Async-Original/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..b15694a2
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Original/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PerformanceImpact-Async-Original")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PerformanceImpact-Async-Original")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a7a642d3-2efa-4eaa-9762-6dc9e0c883a1")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/DevTools/PerformanceImpact-Async-Original/packages.config b/src/DevTools/PerformanceImpact-Async-Original/packages.config
new file mode 100644
index 00000000..52a7d804
--- /dev/null
+++ b/src/DevTools/PerformanceImpact-Async-Original/packages.config
@@ -0,0 +1,4 @@
+
+
+  
+
\ No newline at end of file
diff --git a/src/MoonSharp.Interpreter.Tests/EndToEnd/AsyncTests.cs b/src/MoonSharp.Interpreter.Tests/EndToEnd/AsyncTests.cs
new file mode 100644
index 00000000..2e5a7f55
--- /dev/null
+++ b/src/MoonSharp.Interpreter.Tests/EndToEnd/AsyncTests.cs
@@ -0,0 +1,141 @@
+#if HASDYNAMIC
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace MoonSharp.Interpreter.Tests.EndToEnd
+{
+    [TestFixture]
+    public class AsyncTests
+    {
+        [Test]
+        public void ThreadPausedIfRunAsync()
+        {
+            Script S = new Script();
+
+            S.Globals.Get("os").Table["sleep"] = (Action)((ctx, args) => 
+            {
+                ctx.PauseExecution(TimeSpan.FromSeconds(2));
+            });
+
+            string code = @"
+                local timeStarted = os.clock()
+                os.sleep()
+                local timeEnded = os.clock()
+
+                return timeEnded - timeStarted > 2";
+
+            var ecToken = new ExecutionControlToken();
+            Assert.IsTrue(S.DoStringAsync(ecToken, code).Result.CastToBool());
+        }
+
+        [Test]
+        public void ThreadPausedIfRunSync()
+        {
+            Script S = new Script();
+
+            S.Globals.Get("os").Table["sleep"] = (Action)((ctx, args) =>
+            {
+                ctx.PauseExecution(TimeSpan.FromSeconds(2));
+            });
+
+            string code = @"
+                local timeStarted = os.clock()
+                os.sleep()
+                local timeEnded = os.clock()
+
+                return timeEnded - timeStarted > 2";
+
+            Assert.IsTrue(S.DoString(code).CastToBool());
+        }
+
+        [Test]
+        public void ClrFunctionExecutionCanBeCancelledIfPausedWhenRunAsync()
+        {
+            Script S = new Script();
+
+            S.Globals.Set("pause", DynValue.NewCallback((ctx, args) =>
+            {
+                ctx.PauseExecution(TimeSpan.FromSeconds(20));
+                return DynValue.NewNil();
+            }));
+
+            var ecToken = new ExecutionControlToken();
+
+            Task t = S.CallAsync(ecToken, S.Globals.Get("pause"));
+
+            t.ContinueWith(_ => Assert.Pass(), TaskContinuationOptions.OnlyOnCanceled);
+            t.ContinueWith(t_ => { if (t_.Exception.InnerExceptions.Count != 1 || !(t_.Exception.InnerException.InnerException is ScriptTerminationRequestedException)) { Assert.Fail("task faulted"); } }, TaskContinuationOptions.OnlyOnFaulted);
+            t.ContinueWith(_ => Assert.Fail("task didn't abort"), TaskContinuationOptions.OnlyOnRanToCompletion);
+
+            Thread.Sleep(500);
+            ecToken.Terminate();
+
+            while (t.Status != TaskStatus.Canceled && t.Status != TaskStatus.Faulted && t.Status != TaskStatus.RanToCompletion) { }
+        }
+
+        [Test]
+        public void LuaCodeExecutionCanBeCancelledIfPausedWhenRunAsync()
+        {
+            Script S = new Script();
+
+            S.Globals.Set("pause", DynValue.NewCallback((ctx, args) =>
+            {
+                ctx.PauseExecution(TimeSpan.FromSeconds(20));
+                return DynValue.NewNil();
+            }));
+
+            var ecToken = new ExecutionControlToken();
+
+            Task t = S.DoStringAsync(ecToken, "pause()");
+
+            t.ContinueWith(_ => Assert.Pass(), TaskContinuationOptions.OnlyOnCanceled);
+            t.ContinueWith(t_ => { if (t_.Exception.InnerExceptions.Count != 1 || !(t_.Exception.InnerException.InnerException is ScriptTerminationRequestedException)) { Assert.Fail("task faulted"); } }, TaskContinuationOptions.OnlyOnFaulted);
+            t.ContinueWith(_ => Assert.Fail("task didn't abort"), TaskContinuationOptions.OnlyOnRanToCompletion);
+
+            Thread.Sleep(500);
+            ecToken.Terminate();
+
+            while (t.Status != TaskStatus.Canceled && t.Status != TaskStatus.Faulted && t.Status != TaskStatus.RanToCompletion) { }
+        }
+
+        [Test]
+        public void ExecutionControlTokenCanBeAssociatedWithMultipleScriptsSimultaneously()
+        {
+            var callback = DynValue.NewCallback((ctx, args) =>
+            {
+                ctx.PauseExecution(TimeSpan.FromSeconds(20));
+                return DynValue.NewNil();
+            });
+
+            Script S1 = new Script();
+
+            S1.Globals.Set("pause", callback);
+
+            Script S2 = new Script();
+
+            S2.Globals.Set("pause", callback);
+
+            var ecToken = new ExecutionControlToken();
+
+            Task t1 = S1.DoStringAsync(ecToken, "pause()");
+            Task t2 = S2.DoStringAsync(ecToken, "pause()");
+
+            t1.ContinueWith(t => { foreach (var e in t.Exception.InnerExceptions) { Console.WriteLine(e.InnerException.Message); } }, TaskContinuationOptions.NotOnRanToCompletion);
+            t1.ContinueWith(t => Assert.IsTrue(t1.IsCanceled, "t1 is canceled"), TaskContinuationOptions.OnlyOnCanceled);
+            t1.ContinueWith(t => Assert.Fail(), TaskContinuationOptions.OnlyOnRanToCompletion);
+
+            t2.ContinueWith(t => { foreach (var e in t.Exception.InnerExceptions) { Console.WriteLine(e.InnerException.Message); } }, TaskContinuationOptions.NotOnRanToCompletion);
+            t2.ContinueWith(t => Assert.IsTrue(t2.IsCanceled, "t2 is canceled"), TaskContinuationOptions.OnlyOnCanceled);
+            t2.ContinueWith(t => Assert.Fail(), TaskContinuationOptions.OnlyOnRanToCompletion);
+
+            Thread.Sleep(500);
+            ecToken.Terminate();
+
+            while ((t1.Status != TaskStatus.Canceled && t1.Status != TaskStatus.Faulted && t1.Status != TaskStatus.RanToCompletion) ||
+                   (t2.Status != TaskStatus.Canceled && t2.Status != TaskStatus.Faulted && t2.Status != TaskStatus.RanToCompletion)) { }
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs b/src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs
index 09d4ebfc..d4f81881 100755
--- a/src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs
+++ b/src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs
@@ -291,12 +291,12 @@ public Type Type
 				get { return typeof(SomeOtherClassCustomDescriptor); }
 			}
 
-			public DynValue Index(Script script, object obj, DynValue index, bool dummy)
+			public DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool dummy)
 			{
 				return DynValue.NewNumber(index.Number * 4);
 			}
 
-			public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool dummy)
+			public bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool dummy)
 			{
 				throw new NotImplementedException();
 			}
@@ -306,7 +306,7 @@ public string AsString(object obj)
 				return null;
 			}
 
-			public DynValue MetaIndex(Script script, object obj, string metaname)
+			public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname)
 			{
 				return null;
 			}
@@ -322,17 +322,17 @@ public bool IsTypeCompatible(Type type, object obj)
 
 		public class SelfDescribingClass : IUserDataType
 		{
-			public DynValue Index(Script script, DynValue index, bool isNameIndex)
+			public DynValue Index(ExecutionControlToken ecToken, Script script, DynValue index, bool isNameIndex)
 			{
 				return DynValue.NewNumber(index.Number * 3);
 			}
 
-			public bool SetIndex(Script script, DynValue index, DynValue value, bool isNameIndex)
+			public bool SetIndex(ExecutionControlToken ecToken, Script script, DynValue index, DynValue value, bool isNameIndex)
 			{
 				throw new NotImplementedException();
 			}
 
-			public DynValue MetaIndex(Script script, string metaname)
+			public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, string metaname)
 			{
 				throw new NotImplementedException();
 			}
diff --git a/src/MoonSharp.Interpreter.Tests/EndToEnd/VtUserDataMethodsTests.cs b/src/MoonSharp.Interpreter.Tests/EndToEnd/VtUserDataMethodsTests.cs
index 856e2d16..73280c82 100755
--- a/src/MoonSharp.Interpreter.Tests/EndToEnd/VtUserDataMethodsTests.cs
+++ b/src/MoonSharp.Interpreter.Tests/EndToEnd/VtUserDataMethodsTests.cs
@@ -290,12 +290,12 @@ public Type Type
 				get { return typeof(SomeOtherClassCustomDescriptor); }
 			}
 
-			public DynValue Index(Script script, object obj, DynValue index, bool dummy)
+			public DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool dummy)
 			{
 				return DynValue.NewNumber(index.Number * 4);
 			}
 
-			public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool dummy)
+			public bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool dummy)
 			{
 				throw new NotImplementedException();
 			}
@@ -305,7 +305,7 @@ public string AsString(object obj)
 				return null;
 			}
 
-			public DynValue MetaIndex(Script script, object obj, string metaname)
+			public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname)
 			{
 				return null;
 			}
@@ -321,17 +321,17 @@ public bool IsTypeCompatible(Type type, object obj)
 
 		public struct SelfDescribingClass : IUserDataType
 		{
-			public DynValue Index(Script script, DynValue index, bool isNameIndex)
+			public DynValue Index(ExecutionControlToken ecToken, Script script, DynValue index, bool isNameIndex)
 			{
 				return DynValue.NewNumber(index.Number * 3);
 			}
 
-			public bool SetIndex(Script script, DynValue index, DynValue value, bool isNameIndex)
+			public bool SetIndex(ExecutionControlToken ecToken, Script script, DynValue index, DynValue value, bool isNameIndex)
 			{
 				throw new NotImplementedException();
 			}
 
-			public DynValue MetaIndex(Script script, string metaname)
+			public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, string metaname)
 			{
 				throw new NotImplementedException();
 			}
diff --git a/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.net40-client/MoonSharp.Interpreter.Tests.net40-client.csproj b/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.net40-client/MoonSharp.Interpreter.Tests.net40-client.csproj
index 18489fdf..73153d2c 100644
--- a/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.net40-client/MoonSharp.Interpreter.Tests.net40-client.csproj
+++ b/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.net40-client/MoonSharp.Interpreter.Tests.net40-client.csproj
@@ -213,6 +213,7 @@
     
       _Hardwired.cs
     
+    
   
   
     
diff --git a/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.portable40/MoonSharp.Interpreter.Tests.portable40.csproj b/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.portable40/MoonSharp.Interpreter.Tests.portable40.csproj
index 90d0a48d..3ff9c214 100644
--- a/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.portable40/MoonSharp.Interpreter.Tests.portable40.csproj
+++ b/src/MoonSharp.Interpreter.Tests/_Projects/MoonSharp.Interpreter.Tests.portable40/MoonSharp.Interpreter.Tests.portable40.csproj
@@ -213,6 +213,7 @@
     
       _Hardwired.cs
     
+    
   
   
     
diff --git a/src/MoonSharp.Interpreter/AsyncExtensions.cs b/src/MoonSharp.Interpreter/AsyncExtensions.cs
deleted file mode 100755
index eb0055c5..00000000
--- a/src/MoonSharp.Interpreter/AsyncExtensions.cs
+++ /dev/null
@@ -1,421 +0,0 @@
-#if HASDYNAMIC
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MoonSharp.Interpreter.REPL;
-
-namespace MoonSharp.Interpreter
-{
-	/// 
-	/// This class contains extension methods providing async wrappers of many methods.
-	/// Asynchronous execution is performed by scheduling the method on the thread pool (through a Task.Factory.StartNew).
-	/// 
-	/// This type is supported only on .NET 4.x and .NET 4.x PCL targets.
-	/// 
-	public static class AsyncExtensions
-	{
-		private static Task ExecAsync(Func func)
-		{
-			return Task.Factory.StartNew(func);
-		}
-
-		private static Task ExecAsyncVoid(Action func)
-		{
-			return Task.Factory.StartNew(func);
-		}
-
-
-
-		/// 
-		/// Asynchronously calls this function with the specified args
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The function.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Closure function)
-		{
-			return ExecAsync(() => function.Call());
-		}
-
-		/// 
-		/// Asynchronously calls this function with the specified args
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The function.
-		/// The arguments to pass to the function.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Closure function, params object[] args)
-		{
-			return ExecAsync(() => function.Call(args));
-		}
-
-		/// 
-		/// Asynchronously calls this function with the specified args
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The function.
-		/// The arguments to pass to the function.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Closure function, params DynValue[] args)
-		{
-			return ExecAsync(() => function.Call(args));
-		}
-
-		/// 
-		/// Asynchronously loads and executes a string containing a Lua/MoonSharp script.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The code.
-		/// The global context.
-		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
-		/// 
-		/// A DynValue containing the result of the processing of the loaded chunk.
-		/// 
-		public static Task DoStringAsync(this Script script, string code, Table globalContext = null, string codeFriendlyName = null)
-		{
-			return ExecAsync(() => script.DoString(code, globalContext, codeFriendlyName));
-		}
-
-
-		/// 
-		/// Asynchronously loads and executes a stream containing a Lua/MoonSharp script.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The stream.
-		/// The global context.
-		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
-		/// 
-		/// A DynValue containing the result of the processing of the loaded chunk.
-		/// 
-		public static Task DoStreamAsync(this Script script, Stream stream, Table globalContext = null, string codeFriendlyName = null)
-		{
-			return ExecAsync(() => script.DoStream(stream, globalContext, codeFriendlyName));
-		}
-
-
-		/// 
-		/// Asynchronously loads and executes a file containing a Lua/MoonSharp script.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The filename.
-		/// The global context.
-		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
-		/// 
-		/// A DynValue containing the result of the processing of the loaded chunk.
-		/// 
-		public static Task DoFileAsync(this Script script, string filename, Table globalContext = null, string codeFriendlyName = null)
-		{
-			return ExecAsync(() => script.DoFile(filename, globalContext, codeFriendlyName));
-		}
-
-		/// 
-		/// Asynchronously loads a string containing a Lua/MoonSharp function.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The code.
-		/// The global table to bind to this chunk.
-		/// Name of the function used to report errors, etc.
-		/// 
-		/// A DynValue containing a function which will execute the loaded code.
-		/// 
-		public static Task LoadFunctionAsync(this Script script, string code, Table globalTable = null, string funcFriendlyName = null)
-		{
-			return ExecAsync(() => script.LoadFunction(code, globalTable, funcFriendlyName));
-		}
-
-
-
-		/// 
-		/// Asynchronously loads a string containing a Lua/MoonSharp script.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The code.
-		/// The global table to bind to this chunk.
-		/// Name of the code - used to report errors, etc.
-		/// 
-		/// A DynValue containing a function which will execute the loaded code.
-		/// 
-		public static Task LoadStringAsync(this Script script, string code, Table globalTable = null, string codeFriendlyName = null)
-		{
-			return ExecAsync(() => script.LoadString(code, globalTable, codeFriendlyName));
-		}
-
-
-
-		/// 
-		/// Asynchronously loads a Lua/MoonSharp script from a System.IO.Stream. NOTE: This will *NOT* close the stream!
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The stream containing code.
-		/// The global table to bind to this chunk.
-		/// Name of the code - used to report errors, etc.
-		/// 
-		/// A DynValue containing a function which will execute the loaded code.
-		/// 
-		public static Task LoadStreamAsync(this Script script, Stream stream, Table globalTable = null, string codeFriendlyName = null)
-		{
-			return ExecAsync(() => script.LoadStream(stream, globalTable, codeFriendlyName));
-		}
-
-
-		/// 
-		/// Asynchronously dumps a function on the specified stream.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The function.
-		/// The stream.
-		/// 
-		/// function arg is not a function!
-		/// or
-		/// stream is readonly!
-		/// or
-		/// function arg has upvalues other than _ENV
-		public static Task DumpAsync(this Script script, DynValue function, Stream stream)
-		{
-			return ExecAsyncVoid(() => script.Dump(function, stream));
-		}
-
-
-
-		/// 
-		/// Asynchronously loads a string containing a Lua/MoonSharp script.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The code.
-		/// The global table to bind to this chunk.
-		/// The filename to be used in error messages.
-		/// 
-		/// A DynValue containing a function which will execute the loaded code.
-		/// 
-		public static Task LoadFileAsync(this Script script, string filename, Table globalContext = null, string friendlyFilename = null)
-		{
-			return ExecAsync(() => script.LoadFile(filename, globalContext, friendlyFilename));
-		}
-
-
-
-		/// 
-		/// Calls the specified function.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The Lua/MoonSharp function to be called
-		/// 
-		/// The return value(s) of the function call.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Script script, DynValue function)
-		{
-			return ExecAsync(() => script.Call(function));
-		}
-
-
-		/// 
-		/// Asynchronously calls the specified function.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The Lua/MoonSharp function to be called
-		/// The arguments to pass to the function.
-		/// 
-		/// The return value(s) of the function call.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Script script, DynValue function, params DynValue[] args)
-		{
-			return ExecAsync(() => script.Call(function, args));
-		}
-
-
-
-		/// 
-		/// Asynchronously calls the specified function.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The Lua/MoonSharp function to be called
-		/// The arguments to pass to the function.
-		/// 
-		/// The return value(s) of the function call.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Script script, DynValue function, params object[] args)
-		{
-			return ExecAsync(() => script.Call(function, args));
-		}
-
-
-
-		/// 
-		/// Asynchronously calls the specified function.
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The Lua/MoonSharp function to be called
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Script script, object function)
-		{
-			return ExecAsync(() => script.Call(function));
-		}
-
-
-		/// 
-		/// Asynchronously calls the specified function.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The Lua/MoonSharp function to be called
-		/// The arguments to pass to the function.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public static Task CallAsync(this Script script, object function, params object[] args)
-		{
-			return ExecAsync(() => script.Call(function, args));
-		}
-
-		/// 
-		/// Asynchronously creates a new dynamic expression.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The script.
-		/// The code of the expression.
-		/// 
-		public static Task CreateDynamicExpressionAsync(this Script script, string code)
-		{
-			return ExecAsync(() => script.CreateDynamicExpression(code));
-		}
-
-		/// 
-		/// Asynchronously evaluates a REPL command.
-		/// This method returns the result of the computation, or null if more input is needed for having valid code.
-		/// In case of errors, exceptions are propagated to the caller.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The interpreter.
-		/// The input.
-		/// 
-		/// This method returns the result of the computation, or null if more input is needed for a computation.
-		/// 
-		public static Task EvaluateAsync(this ReplInterpreter interpreter, string input)
-		{
-			return ExecAsync(() => interpreter.Evaluate(input));
-		}
-
-		/// 
-		/// Resumes the coroutine.
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// The arguments.
-		/// 
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead
-		public static Task ResumeAsync(this Coroutine cor, params DynValue[] args)
-		{
-			return ExecAsync(() => cor.Resume(args));
-		}
-
-
-		/// 
-		/// Resumes the coroutine.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// The ScriptExecutionContext.
-		/// The arguments.
-		/// 
-		public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params DynValue[] args)
-		{
-			return ExecAsync(() => cor.Resume(context, args));
-		}
-
-		/// 
-		/// Resumes the coroutine.
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// 
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead
-		public static Task ResumeAsync(this Coroutine cor)
-		{
-			return ExecAsync(() => cor.Resume());
-		}
-
-
-		/// 
-		/// Resumes the coroutine.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// The ScriptExecutionContext.
-		/// 
-		public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context)
-		{
-			return ExecAsync(() => cor.Resume(context));
-		}
-
-		/// 
-		/// Resumes the coroutine.
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// The arguments.
-		/// 
-		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
-		public static Task ResumeAsync(this Coroutine cor, params object[] args)
-		{
-			return ExecAsync(() => cor.Resume(args));
-		}
-
-
-		/// 
-		/// Resumes the coroutine
-		/// 
-		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
-		/// 
-		/// The coroutine
-		/// The ScriptExecutionContext.
-		/// The arguments.
-		/// 
-		public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params object[] args)
-		{
-			return ExecAsync(() => cor.Resume(context, args));
-		}
-	}
-}
-#endif
diff --git a/src/MoonSharp.Interpreter/CoreLib/ErrorHandlingModule.cs b/src/MoonSharp.Interpreter/CoreLib/ErrorHandlingModule.cs
index ffa21d03..b8d3a3fd 100644
--- a/src/MoonSharp.Interpreter/CoreLib/ErrorHandlingModule.cs
+++ b/src/MoonSharp.Interpreter/CoreLib/ErrorHandlingModule.cs
@@ -14,11 +14,12 @@ public class ErrorHandlingModule
 		[MoonSharpModuleMethod]
 		public static DynValue pcall(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
-			return SetErrorHandlerStrategy("pcall", executionContext, args, null);
+			return SetErrorHandlerStrategy(executionContext.m_EcToken, "pcall", executionContext, args, null);
 		}
 
 
-		private static DynValue SetErrorHandlerStrategy(string funcName, 
+		private static DynValue SetErrorHandlerStrategy(ExecutionControlToken ecToken,
+            string funcName, 
 			ScriptExecutionContext executionContext, 
 			CallbackArguments args,
 			DynValue handlerBeforeUnwind)
@@ -125,7 +126,7 @@ public static DynValue xpcall(ScriptExecutionContext executionContext, CallbackA
 				args.AsType(1, "xpcall", DataType.Function, false);
 			}
 
-			return SetErrorHandlerStrategy("xpcall", executionContext, new CallbackArguments(a, false), handler);
+			return SetErrorHandlerStrategy(executionContext.m_EcToken, "xpcall", executionContext, new CallbackArguments(a, false), handler);
 		}
 
 	}
diff --git a/src/MoonSharp.Interpreter/DataTypes/Closure.cs b/src/MoonSharp.Interpreter/DataTypes/Closure.cs
index 0ed8e705..d2884a6e 100644
--- a/src/MoonSharp.Interpreter/DataTypes/Closure.cs
+++ b/src/MoonSharp.Interpreter/DataTypes/Closure.cs
@@ -1,4 +1,7 @@
 using System.Collections.Generic;
+#if HASDYNAMIC
+using System.Threading.Tasks;
+#endif
 using MoonSharp.Interpreter.Execution;
 
 namespace MoonSharp.Interpreter
@@ -103,6 +106,50 @@ public DynValue Call(params DynValue[] args)
 		}
 
 
+#if HASDYNAMIC
+		/// 
+		/// Asynchronously calls this function with the specified args
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The function.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken)
+		{
+			return OwnerScript.CallAsync(ecToken, this);
+		}
+
+		/// 
+		/// Asynchronously calls this function with the specified args
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The function.
+		/// The arguments to pass to the function.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, params object[] args)
+		{
+			return OwnerScript.CallAsync(ecToken, this, args);
+		}
+
+		/// 
+		/// Asynchronously calls this function with the specified args
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The function.
+		/// The arguments to pass to the function.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, params DynValue[] args)
+		{
+			return OwnerScript.CallAsync(ecToken, this, args);
+		}
+#endif
+
+
 		/// 
 		/// Gets a delegate wrapping calls to this scripted function
 		/// 
diff --git a/src/MoonSharp.Interpreter/DataTypes/Coroutine.cs b/src/MoonSharp.Interpreter/DataTypes/Coroutine.cs
index 07132e04..3f9e5b82 100755
--- a/src/MoonSharp.Interpreter/DataTypes/Coroutine.cs
+++ b/src/MoonSharp.Interpreter/DataTypes/Coroutine.cs
@@ -1,6 +1,9 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+#if HASDYNAMIC
+using System.Threading.Tasks;
+#endif
 using MoonSharp.Interpreter.Debugging;
 using MoonSharp.Interpreter.Execution.VM;
 
@@ -237,6 +240,96 @@ public DynValue Resume(ScriptExecutionContext context, params object[] args)
 		}
 
 
+#if HASDYNAMIC
+		/// 
+		/// Resumes the coroutine.
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// The arguments.
+		/// 
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead
+		public Task ResumeAsync(params DynValue[] args)
+		{
+			return Task.Factory.StartNew(() => Resume(args));
+		}
+
+
+		/// 
+		/// Resumes the coroutine.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// The ScriptExecutionContext.
+		/// The arguments.
+		/// 
+		public Task ResumeAsync(ScriptExecutionContext context, params DynValue[] args)
+		{
+			return Task.Factory.StartNew(() => Resume(context, args));
+		}
+
+		/// 
+		/// Resumes the coroutine.
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// 
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead
+		public Task ResumeAsync()
+		{
+			return Task.Factory.StartNew(() => Resume());
+		}
+
+
+		/// 
+		/// Resumes the coroutine.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// The ScriptExecutionContext.
+		/// 
+		public Task ResumeAsync(ScriptExecutionContext context)
+		{
+			return Task.Factory.StartNew(() => Resume(context));
+		}
+
+		/// 
+		/// Resumes the coroutine.
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// The arguments.
+		/// 
+		/// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.
+		public Task ResumeAsync(params object[] args)
+		{
+			return Task.Factory.StartNew(() => Resume(args));
+		}
+
+
+		/// 
+		/// Resumes the coroutine
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The coroutine
+		/// The ScriptExecutionContext.
+		/// The arguments.
+		/// 
+		public Task ResumeAsync(ScriptExecutionContext context, params object[] args)
+		{
+			return Task.Factory.StartNew(() => Resume(context, args));
+		}
+#endif
+
 
 
 		/// 
diff --git a/src/MoonSharp.Interpreter/Errors/ScriptTerminationRequestedException.cs b/src/MoonSharp.Interpreter/Errors/ScriptTerminationRequestedException.cs
new file mode 100644
index 00000000..17e748c2
--- /dev/null
+++ b/src/MoonSharp.Interpreter/Errors/ScriptTerminationRequestedException.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace MoonSharp.Interpreter
+{
+	/// 
+	/// Exception thrown when an async script is requested to abort
+	/// 
+#if !(PCL || ((!UNITY_EDITOR) && (ENABLE_DOTNET)) || NETFX_CORE)
+	[Serializable]
+#endif
+	public class ScriptTerminationRequestedException : InterpreterException
+	{
+		/// 
+		/// Initializes a new instance of the  class.
+		/// 
+		internal ScriptTerminationRequestedException()
+			: base("script has been requested to abort")
+		{
+			DecoratedMessage = Message;
+		}
+	}
+}
diff --git a/src/MoonSharp.Interpreter/Execution/DynamicExpression.cs b/src/MoonSharp.Interpreter/Execution/DynamicExpression.cs
index e53b92c6..32519e6e 100644
--- a/src/MoonSharp.Interpreter/Execution/DynamicExpression.cs
+++ b/src/MoonSharp.Interpreter/Execution/DynamicExpression.cs
@@ -36,7 +36,7 @@ internal DynamicExpression(Script S, string strExpr, DynValue constant)
 		/// 
 		public DynValue Evaluate(ScriptExecutionContext context = null)
 		{
-			context = context ?? OwnerScript.CreateDynamicExecutionContext();
+			context = context ?? OwnerScript.CreateDynamicExecutionContext(ExecutionControlToken.Dummy);
 
 			this.CheckScriptOwnership(context.GetScript());
 
diff --git a/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs b/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs
index 0a42ccfb..84327841 100644
--- a/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs
+++ b/src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs
@@ -12,12 +12,14 @@ public class ScriptExecutionContext : IScriptPrivateResource
 	{
 		Processor m_Processor;
 		CallbackFunction m_Callback;
+		internal ExecutionControlToken m_EcToken;
 
-		internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
+		internal ScriptExecutionContext(ExecutionControlToken ecToken, Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
 		{
 			IsDynamicExecution = isDynamic;
 			m_Processor = p;
 			m_Callback = callBackFunction;
+			m_EcToken = ecToken;
 			CallingLocation = sourceRef;
 		}
 
@@ -74,7 +76,7 @@ public Table GetMetatable(DynValue value)
 		/// 
 		public DynValue GetMetamethod(DynValue value, string metamethod)
 		{
-			return m_Processor.GetMetamethod(value, metamethod);
+			return m_Processor.GetMetamethod(m_EcToken, value, metamethod);
 		}
 
 		/// 
@@ -92,7 +94,7 @@ public DynValue GetMetamethodTailCall(DynValue value, string metamethod, params
 		/// 
 		public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
 		{
-			return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
+			return m_Processor.GetBinaryMetamethod(m_EcToken, op1, op2, eventName);
 		}
 
 		/// 
@@ -248,7 +250,7 @@ public Table CurrentGlobalEnv
 		public void PerformMessageDecorationBeforeUnwind(DynValue messageHandler, ScriptRuntimeException exception)
 		{
 			if (messageHandler != null)
-				exception.DecoratedMessage = m_Processor.PerformMessageDecorationBeforeUnwind(messageHandler, exception.Message, CallingLocation);
+				exception.DecoratedMessage = m_Processor.PerformMessageDecorationBeforeUnwind(m_EcToken, messageHandler, exception.Message, CallingLocation);
 			else
 				exception.DecoratedMessage = exception.Message;
 		}
@@ -265,5 +267,24 @@ public Script OwnerScript
 			get { return this.GetScript(); }
 		}
 
+
+		/// 
+		/// Pauses the script thread for the specified amount of time. 
+		/// 
+		/// 
+		/// Timeout.
+		/// 
+		public void PauseExecution(TimeSpan timeout)
+		{
+			m_EcToken.Wait(timeout);
+
+			// This is not strictly required, but why allow the code
+			// to go back to Processor::Processing_Loop if we can check right here if
+			// we should stop or not?
+			if (m_EcToken.IsAbortRequested)
+			{
+				throw new ScriptTerminationRequestedException();
+			}
+		}
 	}
 }
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor.cs
index 18d689ca..09beee63 100755
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Threading;
 using MoonSharp.Interpreter.DataStructs;
@@ -24,7 +24,6 @@ sealed partial class Processor
 		int m_SavedInstructionPtr = -1;
 		DebugContext m_Debug;
 
-
 		public Processor(Script script, Table globalContext, ByteCode byteCode)
 		{
 			m_ValueStack = new FastStack(STACK_SIZE);
@@ -65,12 +64,12 @@ internal Processor(Processor parentProcessor, Processor recycleProcessor)
 			m_State = CoroutineState.NotStarted;
 		}
 
-		public DynValue Call(DynValue function, DynValue[] args)
+		public DynValue Call(ExecutionControlToken ecToken, DynValue function, DynValue[] args)
 		{
 			List coroutinesStack = m_Parent != null ? m_Parent.m_CoroutinesStack : this.m_CoroutinesStack;
 
 			if (coroutinesStack.Count > 0 && coroutinesStack[coroutinesStack.Count - 1] != this)
-				return coroutinesStack[coroutinesStack.Count - 1].Call(function, args);
+				return coroutinesStack[coroutinesStack.Count - 1].Call(ecToken, function, args);
 
 			EnterProcessor();
 
@@ -83,7 +82,7 @@ public DynValue Call(DynValue function, DynValue[] args)
 				try
 				{
 					int entrypoint = PushClrToScriptStackFrame(CallStackItemFlags.CallEntryPoint, function, args);
-					return Processing_Loop(entrypoint);
+					return Processing_Loop(ecToken, entrypoint);
 				}
 				finally
 				{
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Coroutines.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Coroutines.cs
index be736426..853e3eb1 100644
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Coroutines.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Coroutines.cs
@@ -67,7 +67,7 @@ public DynValue Coroutine_Resume(DynValue[] args)
 				}
 
 				m_State = CoroutineState.Running;
-				DynValue retVal = Processing_Loop(entrypoint);
+				DynValue retVal = Processing_Loop(ExecutionControlToken.Dummy, entrypoint);
 
 				if (retVal.Type == DataType.YieldRequest)
 				{
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs
index f7878780..649d3a05 100755
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs
@@ -256,7 +256,7 @@ private bool ToggleBreakPoint(DebuggerAction action, bool? state)
 		private void RefreshDebugger(bool hard, int instructionPtr)
 		{
 			SourceRef sref = GetCurrentSourceRef(instructionPtr);
-			ScriptExecutionContext context = new ScriptExecutionContext(this, null, sref);
+			ScriptExecutionContext context = new ScriptExecutionContext(ExecutionControlToken.Dummy, this, null, sref);
 
 			List watchList = m_Debug.DebuggerAttached.GetWatchItems();
 			List callStack = Debugger_GetCallStack(sref);
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_IExecutionContext.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_IExecutionContext.cs
index e826f240..99b41ffb 100644
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_IExecutionContext.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_IExecutionContext.cs
@@ -19,7 +19,7 @@ internal Table GetMetatable(DynValue value)
 			}
 		}
 
-		internal DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
+		internal DynValue GetBinaryMetamethod(ExecutionControlToken ecToken, DynValue op1, DynValue op2, string eventName)
 		{
 			var op1_MetaTable = GetMetatable(op1);
 			if (op1_MetaTable != null)
@@ -39,7 +39,7 @@ internal DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventNa
 
 			if (op1.Type == DataType.UserData)
 			{
-				DynValue meta = op1.UserData.Descriptor.MetaIndex(this.m_Script,
+				DynValue meta = op1.UserData.Descriptor.MetaIndex(ecToken, this.m_Script,
 					op1.UserData.Object, eventName);
 
 				if (meta != null)
@@ -48,7 +48,7 @@ internal DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventNa
 
 			if (op2.Type == DataType.UserData)
 			{
-				DynValue meta = op2.UserData.Descriptor.MetaIndex(this.m_Script,
+				DynValue meta = op2.UserData.Descriptor.MetaIndex(ecToken, this.m_Script,
 					op2.UserData.Object, eventName);
 
 				if (meta != null)
@@ -58,11 +58,11 @@ internal DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventNa
 			return null;
 		}
 
-		internal DynValue GetMetamethod(DynValue value, string metamethod)
+		internal DynValue GetMetamethod(ExecutionControlToken ecToken, DynValue value, string metamethod)
 		{
 			if (value.Type == DataType.UserData)
 			{
-				DynValue v = value.UserData.Descriptor.MetaIndex(m_Script, value.UserData.Object, metamethod);
+				DynValue v = value.UserData.Descriptor.MetaIndex(ecToken, m_Script, value.UserData.Object, metamethod);
 				if (v != null)
 					return v;
 			}
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs
index 38c0f63e..8dbd7b5f 100644
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs
@@ -13,7 +13,7 @@ sealed partial class Processor
 
 		internal long AutoYieldCounter = 0;
 
-		private DynValue Processing_Loop(int instructionPtr)
+		private DynValue Processing_Loop(ExecutionControlToken ecToken, int instructionPtr)
 		{
 			// This is the main loop of the processor, has a weird control flow and needs to be as fast as possible.
 			// This sentence is just a convoluted way to say "don't complain about gotos".
@@ -42,6 +42,11 @@ private DynValue Processing_Loop(int instructionPtr)
 						return DynValue.NewForcedYieldReq();
 					}
 
+					if (ecToken.IsAbortRequested)
+					{
+						throw new ScriptTerminationRequestedException();
+					}
+
 					++instructionPtr;
 
 					switch (i.OpCode)
@@ -63,56 +68,56 @@ private DynValue Processing_Loop(int instructionPtr)
 							m_ValueStack.Push(i.Value);
 							break;
 						case OpCode.Add:
-							instructionPtr = ExecAdd(i, instructionPtr);
+							instructionPtr = ExecAdd(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Concat:
-							instructionPtr = ExecConcat(i, instructionPtr);
+							instructionPtr = ExecConcat(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Neg:
-							instructionPtr = ExecNeg(i, instructionPtr);
+							instructionPtr = ExecNeg(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Sub:
-							instructionPtr = ExecSub(i, instructionPtr);
+							instructionPtr = ExecSub(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Mul:
-							instructionPtr = ExecMul(i, instructionPtr);
+							instructionPtr = ExecMul(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Div:
-							instructionPtr = ExecDiv(i, instructionPtr);
+							instructionPtr = ExecDiv(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Mod:
-							instructionPtr = ExecMod(i, instructionPtr);
+							instructionPtr = ExecMod(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Power:
-							instructionPtr = ExecPower(i, instructionPtr);
+							instructionPtr = ExecPower(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Eq:
-							instructionPtr = ExecEq(i, instructionPtr);
+							instructionPtr = ExecEq(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.LessEq:
-							instructionPtr = ExecLessEq(i, instructionPtr);
+							instructionPtr = ExecLessEq(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Less:
-							instructionPtr = ExecLess(i, instructionPtr);
+							instructionPtr = ExecLess(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Len:
-							instructionPtr = ExecLen(i, instructionPtr);
+							instructionPtr = ExecLen(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Call:
 						case OpCode.ThisCall:
-							instructionPtr = Internal_ExecCall(i.NumVal, instructionPtr, null, null, i.OpCode == OpCode.ThisCall, i.Name);
+							instructionPtr = Internal_ExecCall(ecToken, i.NumVal, instructionPtr, null, null, i.OpCode == OpCode.ThisCall, i.Name);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Scalar:
@@ -165,7 +170,7 @@ private DynValue Processing_Loop(int instructionPtr)
 							ExecArgs(i);
 							break;
 						case OpCode.Ret:
-							instructionPtr = ExecRet(i);
+							instructionPtr = ExecRet(ecToken, i);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							if (instructionPtr < 0)
 								goto return_to_native_code;
@@ -187,7 +192,7 @@ private DynValue Processing_Loop(int instructionPtr)
 								m_ValueStack.Push(DynValue.NewPrimeTable());
 							break;
 						case OpCode.IterPrep:
-							ExecIterPrep(i);
+							ExecIterPrep(ecToken, i);
 							break;
 						case OpCode.IterUpd:
 							ExecIterUpd(i);
@@ -218,19 +223,19 @@ private DynValue Processing_Loop(int instructionPtr)
 						case OpCode.Index:
 						case OpCode.IndexN:
 						case OpCode.IndexL:
-							instructionPtr = ExecIndex(i, instructionPtr);
+							instructionPtr = ExecIndex(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.IndexSet:
 						case OpCode.IndexSetN:
 						case OpCode.IndexSetL:
-							instructionPtr = ExecIndexSet(i, instructionPtr);
+							instructionPtr = ExecIndexSet(ecToken, i, instructionPtr);
 							if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
 							break;
 						case OpCode.Invalid:
 							throw new NotImplementedException(string.Format("Invalid opcode : {0}", i.Name));
 						default:
-							throw new NotImplementedException(string.Format("Execution for {0} not implented yet!", i.OpCode));
+							throw new NotImplementedException(string.Format("Execution for {0} not implemented yet!", i.OpCode));
 					}
 				}
 
@@ -272,7 +277,7 @@ private DynValue Processing_Loop(int instructionPtr)
 					var c = m_ExecutionStack.Peek(i);
 
 					if (c.ErrorHandlerBeforeUnwind != null)
-						ex.DecoratedMessage = PerformMessageDecorationBeforeUnwind(c.ErrorHandlerBeforeUnwind, ex.DecoratedMessage, GetCurrentSourceRef(instructionPtr));
+						ex.DecoratedMessage = PerformMessageDecorationBeforeUnwind(ecToken, c.ErrorHandlerBeforeUnwind, ex.DecoratedMessage, GetCurrentSourceRef(instructionPtr));
 				}
 
 
@@ -292,7 +297,7 @@ private DynValue Processing_Loop(int instructionPtr)
 
 						var cbargs = new DynValue[] { DynValue.NewString(ex.DecoratedMessage) };
 
-						DynValue handled = csi.ErrorHandler.Invoke(new ScriptExecutionContext(this, csi.ErrorHandler, GetCurrentSourceRef(instructionPtr)), cbargs);
+						DynValue handled = csi.ErrorHandler.Invoke(new ScriptExecutionContext(ecToken, this, csi.ErrorHandler, GetCurrentSourceRef(instructionPtr)), cbargs);
 
 						m_ValueStack.Push(handled);
 
@@ -316,7 +321,7 @@ private DynValue Processing_Loop(int instructionPtr)
 		}
 
 
-		internal string PerformMessageDecorationBeforeUnwind(DynValue messageHandler, string decoratedMessage, SourceRef sourceRef)
+		internal string PerformMessageDecorationBeforeUnwind(ExecutionControlToken ecToken, DynValue messageHandler, string decoratedMessage, SourceRef sourceRef)
 		{
 			try
 			{
@@ -325,11 +330,11 @@ internal string PerformMessageDecorationBeforeUnwind(DynValue messageHandler, st
 
 				if (messageHandler.Type == DataType.Function)
 				{
-					ret = this.Call(messageHandler, args);
+					ret = this.Call(ecToken, messageHandler, args);
 				}
 				else if (messageHandler.Type == DataType.ClrFunction)
 				{
-					ScriptExecutionContext ctx = new ScriptExecutionContext(this, messageHandler.Callback, sourceRef);
+					ScriptExecutionContext ctx = new ScriptExecutionContext(ecToken, this, messageHandler.Callback, sourceRef);
 					ret = messageHandler.Callback.Invoke(ctx, args);
 				}
 				else
@@ -473,7 +478,7 @@ private void ExecExpTuple(Instruction i)
 
 		}
 
-		private void ExecIterPrep(Instruction i)
+		private void ExecIterPrep(ExecutionControlToken ecToken, Instruction i)
 		{
 			DynValue v = m_ValueStack.Pop();
 
@@ -492,7 +497,7 @@ private void ExecIterPrep(Instruction i)
 
 			if (f.Type != DataType.Function && f.Type != DataType.ClrFunction)
 			{
-				DynValue meta = this.GetMetamethod(f, "__iterator");
+				DynValue meta = this.GetMetamethod(ecToken, f, "__iterator");
 
 				if (meta != null && !meta.IsNil())
 				{
@@ -510,7 +515,7 @@ private void ExecIterPrep(Instruction i)
 				}
 				else if (f.Type == DataType.Table)
 				{
-					DynValue callmeta = this.GetMetamethod(f, "__call");
+					DynValue callmeta = this.GetMetamethod(ecToken, f, "__call");
 
 					if (callmeta == null || callmeta.IsNil())
 					{
@@ -666,7 +671,7 @@ private void ExecArgs(Instruction I)
 
 
 
-		private int Internal_ExecCall(int argsCount, int instructionPtr, CallbackFunction handler = null,
+		private int Internal_ExecCall(ExecutionControlToken ecToken, int argsCount, int instructionPtr, CallbackFunction handler = null,
 			CallbackFunction continuation = null, bool thisCall = false, string debugText = null, DynValue unwindHandler = null)
 		{
 			DynValue fn = m_ValueStack.Peek(argsCount);
@@ -722,13 +727,14 @@ private int Internal_ExecCall(int argsCount, int instructionPtr, CallbackFunctio
 					Flags = flags,
 				});
 
-				var ret = fn.Callback.Invoke(new ScriptExecutionContext(this, fn.Callback, sref), args, isMethodCall: thisCall);
+
+				var ret = fn.Callback.Invoke(new ScriptExecutionContext(ecToken, this, fn.Callback, sref), args, isMethodCall: thisCall);
 				m_ValueStack.RemoveLast(argsCount + 1);
 				m_ValueStack.Push(ret);
 
 				m_ExecutionStack.Pop();
 
-				return Internal_CheckForTailRequests(null, instructionPtr);
+				return Internal_CheckForTailRequests(ecToken, null, instructionPtr);
 			}
 			else if (fn.Type == DataType.Function)
 			{
@@ -749,7 +755,7 @@ private int Internal_ExecCall(int argsCount, int instructionPtr, CallbackFunctio
 			}
 
 			// fallback to __call metamethod
-			var m = GetMetamethod(fn, "__call");
+			var m = GetMetamethod(ecToken, fn, "__call");
 
 			if (m != null && m.IsNotNil())
 			{
@@ -762,7 +768,7 @@ private int Internal_ExecCall(int argsCount, int instructionPtr, CallbackFunctio
 				for (int i = argsCount; i >= 0; i--)
 					m_ValueStack.Push(tmp[i]);
 
-				return Internal_ExecCall(argsCount + 1, instructionPtr, handler, continuation);
+				return Internal_ExecCall(ecToken, argsCount + 1, instructionPtr, handler, continuation);
 			}
 
 			throw ScriptRuntimeException.AttemptToCallNonFunc(fn.Type, debugText);
@@ -792,7 +798,7 @@ private int PerformTCO(int instructionPtr, int argsCount)
 
 
 
-		private int ExecRet(Instruction i)
+		private int ExecRet(ExecutionControlToken ecToken, Instruction i)
 		{
 			CallStackItem csi;
 			int retpoint = 0;
@@ -813,7 +819,7 @@ private int ExecRet(Instruction i)
 				var argscnt = (int)(m_ValueStack.Pop().Number);
 				m_ValueStack.RemoveLast(argscnt + 1);
 				m_ValueStack.Push(retval);
-				retpoint = Internal_CheckForTailRequests(i, retpoint);
+				retpoint = Internal_CheckForTailRequests(ecToken, i, retpoint);
 			}
 			else
 			{
@@ -821,7 +827,7 @@ private int ExecRet(Instruction i)
 			}
 
 			if (csi.Continuation != null)
-				m_ValueStack.Push(csi.Continuation.Invoke(new ScriptExecutionContext(this, csi.Continuation, i.SourceCodeRef),
+				m_ValueStack.Push(csi.Continuation.Invoke(new ScriptExecutionContext(ecToken, this, csi.Continuation, i.SourceCodeRef),
 					new DynValue[1] { m_ValueStack.Pop() }));
 
 			return retpoint;
@@ -829,7 +835,7 @@ private int ExecRet(Instruction i)
 
 
 
-		private int Internal_CheckForTailRequests(Instruction i, int instructionPtr)
+		private int Internal_CheckForTailRequests(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue tail = m_ValueStack.Peek(0);
 
@@ -844,7 +850,7 @@ private int Internal_CheckForTailRequests(Instruction i, int instructionPtr)
 				for (int ii = 0; ii < tcd.Args.Length; ii++)
 					m_ValueStack.Push(tcd.Args[ii]);
 
-				return Internal_ExecCall(tcd.Args.Length, instructionPtr, tcd.ErrorHandler, tcd.Continuation, false, null, tcd.ErrorHandlerBeforeUnwind);
+				return Internal_ExecCall(ecToken, tcd.Args.Length, instructionPtr, tcd.ErrorHandler, tcd.Continuation, false, null, tcd.ErrorHandlerBeforeUnwind);
 			}
 			else if (tail.Type == DataType.YieldRequest)
 			{
@@ -886,7 +892,7 @@ private int ExecShortCircuitingOperator(Instruction i, int instructionPtr)
 		}
 
 
-		private int ExecAdd(Instruction i, int instructionPtr)
+		private int ExecAdd(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -901,13 +907,13 @@ private int ExecAdd(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__add", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__add", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 		}
 
-		private int ExecSub(Instruction i, int instructionPtr)
+		private int ExecSub(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -922,14 +928,14 @@ private int ExecSub(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__sub", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__sub", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 		}
 
 
-		private int ExecMul(Instruction i, int instructionPtr)
+		private int ExecMul(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -944,13 +950,13 @@ private int ExecMul(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mul", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__mul", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 		}
 
-		private int ExecMod(Instruction i, int instructionPtr)
+		private int ExecMod(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -967,13 +973,13 @@ private int ExecMod(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mod", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__mod", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 		}
 
-		private int ExecDiv(Instruction i, int instructionPtr)
+		private int ExecDiv(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -988,12 +994,12 @@ private int ExecDiv(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__div", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 		}
-		private int ExecPower(Instruction i, int instructionPtr)
+		private int ExecPower(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -1008,14 +1014,14 @@ private int ExecPower(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__pow", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__pow", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
 			}
 
 		}
 
-		private int ExecNeg(Instruction i, int instructionPtr)
+		private int ExecNeg(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			double? rn = r.CastToNumber();
@@ -1027,14 +1033,14 @@ private int ExecNeg(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeUnaryMetaMethod(r, "__unm", instructionPtr);
+				int ip = Internal_InvokeUnaryMetaMethod(ecToken, r, "__unm", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ArithmeticOnNonNumber(r);
 			}
 		}
 
 
-		private int ExecEq(Instruction i, int instructionPtr)
+		private int ExecEq(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -1049,7 +1055,7 @@ private int ExecEq(Instruction i, int instructionPtr)
 			// then if they are userdatas, attempt meta
 			if (l.Type == DataType.UserData || r.Type == DataType.UserData)
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__eq", instructionPtr);
 				if (ip >= 0) return ip;
 			}
 
@@ -1067,7 +1073,7 @@ private int ExecEq(Instruction i, int instructionPtr)
 			// then attempt metatables for tables
 			if ((l.Type == DataType.Table) && (GetMetatable(l) != null) && (GetMetatable(l) == GetMetatable(r)))
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__eq", instructionPtr);
 				if (ip >= 0) return ip;
 			}
 
@@ -1076,7 +1082,7 @@ private int ExecEq(Instruction i, int instructionPtr)
 			return instructionPtr;
 		}
 
-		private int ExecLess(Instruction i, int instructionPtr)
+		private int ExecLess(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -1091,7 +1097,7 @@ private int ExecLess(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__lt", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__lt", instructionPtr);
 				if (ip < 0)
 					throw ScriptRuntimeException.CompareInvalidType(l, r);
 				else
@@ -1102,7 +1108,7 @@ private int ExecLess(Instruction i, int instructionPtr)
 		}
 
 
-		private int ExecLessEq(Instruction i, int instructionPtr)
+		private int ExecLessEq(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -1119,10 +1125,10 @@ private int ExecLessEq(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__le", instructionPtr, DynValue.False);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__le", instructionPtr, DynValue.False);
 				if (ip < 0)
 				{
-					ip = Internal_InvokeBinaryMetaMethod(r, l, "__lt", instructionPtr, DynValue.True);
+					ip = Internal_InvokeBinaryMetaMethod(ecToken, r, l, "__lt", instructionPtr, DynValue.True);
 
 					if (ip < 0)
 						throw ScriptRuntimeException.CompareInvalidType(l, r);
@@ -1136,7 +1142,7 @@ private int ExecLessEq(Instruction i, int instructionPtr)
 			return instructionPtr;
 		}
 
-		private int ExecLen(Instruction i, int instructionPtr)
+		private int ExecLen(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 
@@ -1144,7 +1150,7 @@ private int ExecLen(Instruction i, int instructionPtr)
 				m_ValueStack.Push(DynValue.NewNumber(r.String.Length));
 			else
 			{
-				int ip = Internal_InvokeUnaryMetaMethod(r, "__len", instructionPtr);
+				int ip = Internal_InvokeUnaryMetaMethod(ecToken, r, "__len", instructionPtr);
 				if (ip >= 0)
 					return ip;
 				else if (r.Type == DataType.Table)
@@ -1157,7 +1163,7 @@ private int ExecLen(Instruction i, int instructionPtr)
 		}
 
 
-		private int ExecConcat(Instruction i, int instructionPtr)
+		private int ExecConcat(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			DynValue r = m_ValueStack.Pop().ToScalar();
 			DynValue l = m_ValueStack.Pop().ToScalar();
@@ -1172,7 +1178,7 @@ private int ExecConcat(Instruction i, int instructionPtr)
 			}
 			else
 			{
-				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__concat", instructionPtr);
+				int ip = Internal_InvokeBinaryMetaMethod(ecToken, l, r, "__concat", instructionPtr);
 				if (ip >= 0) return ip;
 				else throw ScriptRuntimeException.ConcatOnNonString(l, r);
 			}
@@ -1205,7 +1211,7 @@ private void ExecTblInitN(Instruction i)
 			tbl.Table.Set(key, val.ToScalar());
 		}
 
-		private int ExecIndexSet(Instruction i, int instructionPtr)
+		private int ExecIndexSet(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here
 
@@ -1249,7 +1255,7 @@ private int ExecIndexSet(Instruction i, int instructionPtr)
 				{
 					UserData ud = obj.UserData;
 
-					if (!ud.Descriptor.SetIndex(this.GetScript(), ud.Object, originalIdx, value, isNameIndex))
+					if (!ud.Descriptor.SetIndex(ecToken, this.GetScript(), ud.Object, originalIdx, value, isNameIndex))
 					{
 						throw ScriptRuntimeException.UserDataMissingField(ud.Descriptor.Name, idx.String);
 					}
@@ -1273,7 +1279,7 @@ private int ExecIndexSet(Instruction i, int instructionPtr)
 					m_ValueStack.Push(obj);
 					m_ValueStack.Push(idx);
 					m_ValueStack.Push(value);
-					return Internal_ExecCall(3, instructionPtr);
+					return Internal_ExecCall(ecToken, 3, instructionPtr);
 				}
 				else
 				{
@@ -1284,7 +1290,7 @@ private int ExecIndexSet(Instruction i, int instructionPtr)
 			throw ScriptRuntimeException.LoopInNewIndex();
 		}
 
-		private int ExecIndex(Instruction i, int instructionPtr)
+		private int ExecIndex(ExecutionControlToken ecToken, Instruction i, int instructionPtr)
 		{
 			int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here
 
@@ -1331,7 +1337,7 @@ private int ExecIndex(Instruction i, int instructionPtr)
 				{
 					UserData ud = obj.UserData;
 
-					var v = ud.Descriptor.Index(this.GetScript(), ud.Object, originalIdx, isNameIndex);
+					var v = ud.Descriptor.Index(ecToken, this.GetScript(), ud.Object, originalIdx, isNameIndex);
 
 					if (v == null)
 					{
@@ -1355,7 +1361,7 @@ private int ExecIndex(Instruction i, int instructionPtr)
 					m_ValueStack.Push(h);
 					m_ValueStack.Push(obj);
 					m_ValueStack.Push(idx);
-					return Internal_ExecCall(2, instructionPtr);
+					return Internal_ExecCall(ecToken, 2, instructionPtr);
 				}
 				else
 				{
diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs
index 3ad7253d..69aa8dee 100644
--- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs
+++ b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs
@@ -44,13 +44,13 @@ private DynValue[] Internal_AdjustTuple(IList values)
 
 
 
-		private int Internal_InvokeUnaryMetaMethod(DynValue op1, string eventName, int instructionPtr)
+		private int Internal_InvokeUnaryMetaMethod(ExecutionControlToken ecToken, DynValue op1, string eventName, int instructionPtr)
 		{
 			DynValue m = null;
 
 			if (op1.Type == DataType.UserData)
 			{
-				m = op1.UserData.Descriptor.MetaIndex(m_Script, op1.UserData.Object, eventName);
+				m = op1.UserData.Descriptor.MetaIndex(ecToken, m_Script, op1.UserData.Object, eventName);
 			}
 
 			if (m == null)
@@ -69,16 +69,16 @@ private int Internal_InvokeUnaryMetaMethod(DynValue op1, string eventName, int i
 			{
 				m_ValueStack.Push(m);
 				m_ValueStack.Push(op1);
-				return Internal_ExecCall(1, instructionPtr);
+				return Internal_ExecCall(ecToken, 1, instructionPtr);
 			}
 			else
 			{
 				return -1;
 			}
 		}
-		private int Internal_InvokeBinaryMetaMethod(DynValue l, DynValue r, string eventName, int instructionPtr, DynValue extraPush = null)
+		private int Internal_InvokeBinaryMetaMethod(ExecutionControlToken ecToken, DynValue l, DynValue r, string eventName, int instructionPtr, DynValue extraPush = null)
 		{
-			var m = GetBinaryMetamethod(l, r, eventName);
+			var m = GetBinaryMetamethod(ecToken, l, r, eventName);
 
 			if (m != null)
 			{
@@ -88,7 +88,7 @@ private int Internal_InvokeBinaryMetaMethod(DynValue l, DynValue r, string event
 				m_ValueStack.Push(m);
 				m_ValueStack.Push(l);
 				m_ValueStack.Push(r);
-				return Internal_ExecCall(2, instructionPtr);
+				return Internal_ExecCall(ecToken, 2, instructionPtr);
 			}
 			else
 			{
diff --git a/src/MoonSharp.Interpreter/ExecutionControlToken.cs b/src/MoonSharp.Interpreter/ExecutionControlToken.cs
new file mode 100644
index 00000000..51ab9d48
--- /dev/null
+++ b/src/MoonSharp.Interpreter/ExecutionControlToken.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+
+namespace MoonSharp.Interpreter
+{
+	/// 
+	/// This class provides an interface to control execution of Lua scripts ran asynchronously.
+	/// 
+	/// This class is supported only on .NET 4.x and .NET 4.x PCL targets. 
+	/// On other targets, it acts as a dummy.
+	/// 
+	public class ExecutionControlToken
+	{
+		public static readonly ExecutionControlToken Dummy = new ExecutionControlToken() { m_IsDummy = true };
+
+#if HASDYNAMIC
+		CancellationTokenSource m_CancellationTokenSource = new CancellationTokenSource();
+#endif
+
+		bool m_IsDummy;
+
+		/// 
+		///  Creates an usable execution control token.
+		/// 
+		/// 
+		public ExecutionControlToken()
+		{
+			m_IsDummy = false;
+		}
+
+		/// 
+		///  Aborts the execution of the script that is associated with this token.
+		/// 
+		public void Terminate()
+		{
+#if HASDYNAMIC
+			if (!m_IsDummy)
+			{
+				m_CancellationTokenSource.Cancel(true);
+			}
+#endif
+		}
+
+		internal bool IsAbortRequested
+		{
+			get
+			{
+#if HASDYNAMIC
+				return m_CancellationTokenSource.IsCancellationRequested;
+#else
+				return false;
+#endif
+			}
+		}
+
+		internal void Wait(TimeSpan timeSpan)
+		{
+#if HASDYNAMIC
+			m_CancellationTokenSource.Token.WaitHandle.WaitOne(timeSpan);
+#else
+			Thread.Sleep(timeSpan);
+#endif
+			
+		}
+	}
+}
diff --git a/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
index 8867be86..98f33782 100644
--- a/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/BasicDescriptors/DispatchingUserDataDescriptor.cs
@@ -210,12 +210,13 @@ private void AddMemberTo(Dictionary members, string n
 		/// 
 		/// Performs an "index" "get" operation. This tries to resolve minor variations of member names.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public virtual DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing)
+		public virtual DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool isDirectIndexing)
 		{
 			if (!isDirectIndexing)
 			{
@@ -224,7 +225,7 @@ public virtual DynValue Index(Script script, object obj, DynValue index, bool is
 					.WithAccessOrNull(MemberDescriptorAccess.CanExecute);
 
 				if (mdesc != null)
-					return ExecuteIndexer(mdesc, script, obj, index, null);
+					return ExecuteIndexer(ecToken, mdesc, script, obj, index, null);
 			}
 
 			index = index.ToScalar();
@@ -323,7 +324,7 @@ protected virtual DynValue TryIndex(Script script, object obj, string indexName)
 		/// The value to be set
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public virtual bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
+		public virtual bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
 		{
 			if (!isDirectIndexing)
 			{
@@ -333,7 +334,7 @@ public virtual bool SetIndex(Script script, object obj, DynValue index, DynValue
 
 				if (mdesc != null)
 				{
-					ExecuteIndexer(mdesc, script, obj, index, value);
+					ExecuteIndexer(ecToken, mdesc, script, obj, index, value);
 					return true;
 				}
 			}
@@ -427,7 +428,7 @@ public virtual string AsString(object obj)
 		/// The dynvalue to set on a setter, or null.
 		/// 
 		/// 
-		protected virtual DynValue ExecuteIndexer(IMemberDescriptor mdesc, Script script, object obj, DynValue index, DynValue value)
+		protected virtual DynValue ExecuteIndexer(ExecutionControlToken ecToken, IMemberDescriptor mdesc, Script script, object obj, DynValue index, DynValue value)
 		{
 			IList values;
 
@@ -456,7 +457,7 @@ protected virtual DynValue ExecuteIndexer(IMemberDescriptor mdesc, Script script
 			}
 
 			CallbackArguments args = new CallbackArguments(values, false);
-			ScriptExecutionContext execCtx = script.CreateDynamicExecutionContext();
+			ScriptExecutionContext execCtx = script.CreateDynamicExecutionContext(ecToken);
 
 			DynValue v = mdesc.GetValue(script, obj);
 
@@ -485,12 +486,13 @@ protected virtual DynValue ExecuteIndexer(IMemberDescriptor mdesc, Script script
 		/// __tonumber is dispatched to implicit or explicit conversion operators to standard numeric types.
 		/// __tobool is dispatched to an implicit or explicit conversion operator to bool. If that fails, operator true is used.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The name of the metamember.
 		/// 
 		/// 
-		public virtual DynValue MetaIndex(Script script, object obj, string metaname)
+		public virtual DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname)
 		{
 			IMemberDescriptor desc = m_MetaMembers.GetOrDefault(metaname);
 
diff --git a/src/MoonSharp.Interpreter/Interop/IUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/IUserDataDescriptor.cs
index b93c8092..0b80218a 100644
--- a/src/MoonSharp.Interpreter/Interop/IUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/IUserDataDescriptor.cs
@@ -18,22 +18,24 @@ public interface IUserDataDescriptor
 		/// 
 		/// Performs an "index" "get" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing);
+		DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool isDirectIndexing);
 		/// 
 		/// Performs an "index" "set" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// The value to be set
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing);
+		bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing);
 		/// 
 		/// Converts this userdata to string
 		/// 
@@ -54,11 +56,12 @@ public interface IUserDataDescriptor
 		/// __index, __newindex, __tostring
 		/// 
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The name of the metamember.
 		/// 
-		DynValue MetaIndex(Script script, object obj, string metaname);
+		DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname);
 		/// 
 		/// Determines whether the specified object is compatible with the specified type.
 		/// Unless a very specific behaviour is needed, the correct implementation is a 
diff --git a/src/MoonSharp.Interpreter/Interop/IUserDataType.cs b/src/MoonSharp.Interpreter/Interop/IUserDataType.cs
index 9ae18bbe..98b6253f 100644
--- a/src/MoonSharp.Interpreter/Interop/IUserDataType.cs
+++ b/src/MoonSharp.Interpreter/Interop/IUserDataType.cs
@@ -11,20 +11,22 @@ public interface IUserDataType
 		/// 
 		/// Performs an "index" "get" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The index.
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		DynValue Index(Script script, DynValue index, bool isDirectIndexing);
+		DynValue Index(ExecutionControlToken ecToken, Script script, DynValue index, bool isDirectIndexing);
 		/// 
 		/// Performs an "index" "set" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The index.
 		/// The value to be set
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		bool SetIndex(Script script, DynValue index, DynValue value, bool isDirectIndexing);
+		bool SetIndex(ExecutionControlToken ecToken, Script script, DynValue index, DynValue value, bool isDirectIndexing);
 		/// 
 		/// 
 		/// Gets a "meta" operation on this userdata. If a descriptor does not support this functionality,
@@ -39,9 +41,10 @@ public interface IUserDataType
 		/// __index, __newindex, __tostring
 		/// 
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The name of the metamember.
 		/// 
-		DynValue MetaIndex(Script script, string metaname);
+		DynValue MetaIndex(ExecutionControlToken ecToken, Script script, string metaname);
 	}
 }
diff --git a/src/MoonSharp.Interpreter/Interop/PredefinedUserData/EnumerableWrapper.cs b/src/MoonSharp.Interpreter/Interop/PredefinedUserData/EnumerableWrapper.cs
index 6accf2ad..f6e32bad 100644
--- a/src/MoonSharp.Interpreter/Interop/PredefinedUserData/EnumerableWrapper.cs
+++ b/src/MoonSharp.Interpreter/Interop/PredefinedUserData/EnumerableWrapper.cs
@@ -61,7 +61,7 @@ internal static DynValue ConvertTable(Table table)
 		}
 
 
-		public DynValue Index(Script script, DynValue index, bool isDirectIndexing)
+		public DynValue Index(ExecutionControlToken ecToken, Script script, DynValue index, bool isDirectIndexing)
 		{
 			if (index.Type == DataType.String)
 			{
@@ -83,12 +83,12 @@ public DynValue Index(Script script, DynValue index, bool isDirectIndexing)
 			return null;
 		}
 
-		public bool SetIndex(Script script, DynValue index, DynValue value, bool isDirectIndexing)
+		public bool SetIndex(ExecutionControlToken ecToken, Script script, DynValue index, DynValue value, bool isDirectIndexing)
 		{
 			return false;
 		}
 
-		public DynValue MetaIndex(Script script, string metaname)
+		public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, string metaname)
 		{
 			if (metaname == "__call")
 				return DynValue.NewCallback(LuaIteratorCallback);
diff --git a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/AutoDescribingUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/AutoDescribingUserDataDescriptor.cs
index ea7bb48d..8cf779d1 100644
--- a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/AutoDescribingUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/AutoDescribingUserDataDescriptor.cs
@@ -42,17 +42,18 @@ public Type Type
 		/// 
 		/// Performs an "index" "get" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing)
+		public DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool isDirectIndexing)
 		{
 			IUserDataType u = obj as IUserDataType;
 
 			if (u != null)
-				return u.Index(script, index, isDirectIndexing);
+				return u.Index(ecToken, script, index, isDirectIndexing);
 
 			return null;
 		}
@@ -60,18 +61,19 @@ public DynValue Index(Script script, object obj, DynValue index, bool isDirectIn
 		/// 
 		/// Performs an "index" "set" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// The value to be set
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
+		public bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing)
 		{
 			IUserDataType u = obj as IUserDataType;
 
 			if (u != null)
-				return u.SetIndex(script, index, value, isDirectIndexing);
+				return u.SetIndex(ecToken, script, index, value, isDirectIndexing);
 
 			return false;
 		}
@@ -99,16 +101,17 @@ public string AsString(object obj)
 		/// These standard metamethods are supported through other calls for efficiency:
 		/// __index, __newindex, __tostring
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The name of the metamember.
 		/// 
-		public DynValue MetaIndex(Script script, object obj, string metaname)
+		public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname)
 		{
 			IUserDataType u = obj as IUserDataType;
 
 			if (u != null)
-				return u.MetaIndex(script, metaname);
+				return u.MetaIndex(ecToken, script, metaname);
 
 			return null;
 		}
diff --git a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/CompositeUserDataDescriptor.cs b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/CompositeUserDataDescriptor.cs
index a7e1a528..ec262210 100644
--- a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/CompositeUserDataDescriptor.cs
+++ b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/CompositeUserDataDescriptor.cs
@@ -55,16 +55,17 @@ public Type Type
 		/// 
 		/// Performs an "index" "get" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public DynValue Index(Script script, object obj, DynValue index, bool isNameIndex)
+		public DynValue Index(ExecutionControlToken ecToken, Script script, object obj, DynValue index, bool isNameIndex)
 		{
 			foreach (IUserDataDescriptor dd in m_Descriptors)
 			{
-				DynValue v = dd.Index(script, obj, index, isNameIndex);
+				DynValue v = dd.Index(ecToken, script, obj, index, isNameIndex);
 
 				if (v != null)
 					return v;
@@ -75,17 +76,18 @@ public DynValue Index(Script script, object obj, DynValue index, bool isNameInde
 		/// 
 		/// Performs an "index" "set" operation.
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The index.
 		/// The value to be set
 		/// If set to true, it's indexed with a name, if false it's indexed through brackets.
 		/// 
-		public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isNameIndex)
+		public bool SetIndex(ExecutionControlToken ecToken, Script script, object obj, DynValue index, DynValue value, bool isNameIndex)
 		{
 			foreach (IUserDataDescriptor dd in m_Descriptors)
 			{
-				if (dd.SetIndex(script, obj, index, value, isNameIndex))
+				if (dd.SetIndex(ecToken, script, obj, index, value, isNameIndex))
 					return true;
 			}
 			return false;
@@ -112,15 +114,16 @@ public string AsString(object obj)
 		/// These standard metamethods are supported through other calls for efficiency:
 		/// __index, __newindex, __tostring
 		/// 
+		/// The execution control token of the script processing thread
 		/// The script originating the request
 		/// The object (null if a static request is done)
 		/// The name of the metamember.
 		/// 
-		public DynValue MetaIndex(Script script, object obj, string metaname)
+		public DynValue MetaIndex(ExecutionControlToken ecToken, Script script, object obj, string metaname)
 		{
 			foreach (IUserDataDescriptor dd in m_Descriptors)
 			{
-				DynValue v = dd.MetaIndex(script, obj, metaname);
+				DynValue v = dd.MetaIndex(ecToken, script, obj, metaname);
 
 				if (v != null)
 					return v;
diff --git a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/EventFacade.cs b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/EventFacade.cs
index 6b9d98b8..6f2043dc 100644
--- a/src/MoonSharp.Interpreter/Interop/StandardDescriptors/EventFacade.cs
+++ b/src/MoonSharp.Interpreter/Interop/StandardDescriptors/EventFacade.cs
@@ -25,7 +25,7 @@ public EventFacade(Func
   
-    
     
     
     
@@ -150,6 +149,8 @@
     
     
     
+    
+    
     
     
     
diff --git a/src/MoonSharp.Interpreter/REPL/ReplInterpreter.cs b/src/MoonSharp.Interpreter/REPL/ReplInterpreter.cs
index 155abd0e..b7137fea 100644
--- a/src/MoonSharp.Interpreter/REPL/ReplInterpreter.cs
+++ b/src/MoonSharp.Interpreter/REPL/ReplInterpreter.cs
@@ -1,4 +1,7 @@
 using System;
+#if HASDYNAMIC
+using System.Threading.Tasks;
+#endif
 
 namespace MoonSharp.Interpreter.REPL
 {
@@ -115,5 +118,24 @@ public virtual DynValue Evaluate(string input)
 				throw;
 			}
 		}
+
+#if HASDYNAMIC
+		/// 
+		/// Asynchronously evaluates a REPL command.
+		/// This method returns the result of the computation, or null if more input is needed for having valid code.
+		/// In case of errors, exceptions are propagated to the caller.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The interpreter.
+		/// The input.
+		/// 
+		/// This method returns the result of the computation, or null if more input is needed for a computation.
+		/// 
+		public Task EvaluateAsync(string input)
+		{
+			return Task.Factory.StartNew(() => Evaluate(input));
+		}
+#endif
 	}
 }
diff --git a/src/MoonSharp.Interpreter/Script.cs b/src/MoonSharp.Interpreter/Script.cs
index 19dd5141..41c13432 100755
--- a/src/MoonSharp.Interpreter/Script.cs
+++ b/src/MoonSharp.Interpreter/Script.cs
@@ -3,6 +3,9 @@
 using System.IO;
 using System.Linq;
 using System.Text;
+#if HASDYNAMIC
+using System.Threading.Tasks;
+#endif
 using MoonSharp.Interpreter.CoreLib;
 using MoonSharp.Interpreter.Debugging;
 using MoonSharp.Interpreter.Diagnostics;
@@ -363,7 +366,6 @@ public DynValue DoFile(string filename, Table globalContext = null, string codeF
 			return Call(func);
 		}
 
-
 		/// 
 		/// Runs the specified file with all possible defaults for quick experimenting.
 		/// 
@@ -442,23 +444,14 @@ public DynValue Call(DynValue function)
 			return Call(function, new DynValue[0]);
 		}
 
-		/// 
-		/// Calls the specified function.
-		/// 
-		/// The Lua/MoonSharp function to be called
-		/// The arguments to pass to the function.
-		/// 
-		/// The return value(s) of the function call.
-		/// 
-		/// Thrown if function is not of DataType.Function
-		public DynValue Call(DynValue function, params DynValue[] args)
+		private DynValue Internal_Call(ExecutionControlToken ecToken, DynValue function, params DynValue[] args)
 		{
 			this.CheckScriptOwnership(function);
 			this.CheckScriptOwnership(args);
 
 			if (function.Type != DataType.Function && function.Type != DataType.ClrFunction)
 			{
-				DynValue metafunction = m_MainProcessor.GetMetamethod(function, "__call");
+				DynValue metafunction = m_MainProcessor.GetMetamethod(ecToken, function, "__call");
 
 				if (metafunction != null)
 				{
@@ -477,10 +470,24 @@ public DynValue Call(DynValue function, params DynValue[] args)
 			}
 			else if (function.Type == DataType.ClrFunction)
 			{
-				return function.Callback.ClrCallback(this.CreateDynamicExecutionContext(function.Callback), new CallbackArguments(args, false));
+				return function.Callback.ClrCallback(this.CreateDynamicExecutionContext(ecToken, function.Callback), new CallbackArguments(args, false));
 			}
 
-			return m_MainProcessor.Call(function, args);
+			return m_MainProcessor.Call(ecToken, function, args);
+		}
+
+		/// 
+		/// Calls the specified function.
+		/// 
+		/// The Lua/MoonSharp function to be called
+		/// The arguments to pass to the function.
+		/// 
+		/// The return value(s) of the function call.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public DynValue Call(DynValue function, params DynValue[] args)
+		{
+			return Internal_Call(ExecutionControlToken.Dummy, function, args);
 		}
 
 		/// 
@@ -525,6 +532,249 @@ public DynValue Call(object function, params object[] args)
 			return Call(DynValue.FromObject(this, function), args);
 		}
 
+
+#if HASDYNAMIC
+		/// 
+		/// Asynchronously loads and executes a string containing a Lua/MoonSharp script.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The code.
+		/// The global context.
+		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
+		/// 
+		/// A DynValue containing the result of the processing of the loaded chunk.
+		/// 
+		public Task DoStringAsync(ExecutionControlToken ecToken, string code, Table globalContext = null, string codeFriendlyName = null)
+		{
+			return LoadStringAsync(code, globalContext, codeFriendlyName)
+				.ContinueWith((Task prevTask) => CallAsync(ecToken, prevTask.Result).Result);
+		}
+
+
+		/// 
+		/// Asynchronously loads and executes a stream containing a Lua/MoonSharp script.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The stream.
+		/// The global context.
+		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
+		/// 
+		/// A DynValue containing the result of the processing of the loaded chunk.
+		/// 
+		public Task DoStreamAsync(ExecutionControlToken ecToken, Stream stream, Table globalContext = null, string codeFriendlyName = null)
+		{
+			return LoadStreamAsync(stream, globalContext, codeFriendlyName)
+				.ContinueWith((Task prevTask) => CallAsync(ecToken, prevTask.Result).Result);
+		}
+
+
+		/// 
+		/// Asynchronously loads and executes a file containing a Lua/MoonSharp script.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The filename.
+		/// The global context.
+		/// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.
+		/// 
+		/// A DynValue containing the result of the processing of the loaded chunk.
+		/// 
+		public Task DoFileAsync(ExecutionControlToken ecToken, string filename, Table globalContext = null, string codeFriendlyName = null)
+		{
+			return LoadFileAsync(filename, globalContext, codeFriendlyName)
+				.ContinueWith((Task prevTask) => CallAsync(ecToken, prevTask.Result).Result);
+		}
+
+
+		/// 
+		/// Asynchronously loads a string containing a Lua/MoonSharp script.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The code.
+		/// The global table to bind to this chunk.
+		/// Name of the code - used to report errors, etc.
+		/// 
+		/// A DynValue containing a function which will execute the loaded code.
+		/// 
+		public Task LoadStringAsync(string code, Table globalTable = null, string codeFriendlyName = null)
+		{
+			return Task.Factory.StartNew(() => LoadString(code, globalTable, codeFriendlyName));
+		}
+
+
+		/// 
+		/// Asynchronously loads a Lua/MoonSharp script from a System.IO.Stream. NOTE: This will *NOT* close the stream!
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The stream containing code.
+		/// The global table to bind to this chunk.
+		/// Name of the code - used to report errors, etc.
+		/// 
+		/// A DynValue containing a function which will execute the loaded code.
+		/// 
+		public Task LoadStreamAsync(Stream stream, Table globalTable = null, string codeFriendlyName = null)
+		{
+			return Task.Factory.StartNew(() => LoadStream(stream, globalTable, codeFriendlyName));
+		}
+
+
+		/// 
+		/// Asynchronously loads a string containing a Lua/MoonSharp script.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The code.
+		/// The global table to bind to this chunk.
+		/// The filename to be used in error messages.
+		/// 
+		/// A DynValue containing a function which will execute the loaded code.
+		/// 
+		public Task LoadFileAsync(string filename, Table globalContext = null, string friendlyFilename = null)
+		{
+			return Task.Factory.StartNew(() => LoadFile(filename, globalContext, friendlyFilename));
+		}
+
+
+		/// 
+		/// Asynchronously loads a string containing a Lua/MoonSharp function.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The code.
+		/// The global table to bind to this chunk.
+		/// Name of the function used to report errors, etc.
+		/// 
+		/// A DynValue containing a function which will execute the loaded code.
+		/// 
+		public Task LoadFunctionAsync(string code, Table globalTable = null, string funcFriendlyName = null)
+		{
+			return Task.Factory.StartNew(() => LoadFunction(code, globalTable, funcFriendlyName));
+		}
+
+
+		/// 
+		/// Asynchronously dumps a function on the specified stream.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The function.
+		/// The stream.
+		/// 
+		/// function arg is not a function!
+		/// or
+		/// stream is readonly!
+		/// or
+		/// function arg has upvalues other than _ENV
+		public Task DumpAsync(DynValue function, Stream stream)
+		{
+			return Task.Factory.StartNew(() => Dump(function, stream));
+		}
+
+
+		/// 
+		/// Calls the specified function.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The Lua/MoonSharp function to be called
+		/// 
+		/// The return value(s) of the function call.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, DynValue function)
+		{
+			return CallAsync(ecToken, function, new DynValue[0]);
+		}
+
+
+		/// 
+		/// Asynchronously calls the specified function.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The Lua/MoonSharp function to be called
+		/// The arguments to pass to the function.
+		/// 
+		/// The return value(s) of the function call.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, DynValue function, params DynValue[] args)
+		{
+			return Task.Factory.StartNew(() => Internal_Call(ecToken, function, args));
+		}
+
+
+		/// 
+		/// Asynchronously calls the specified function.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The Lua/MoonSharp function to be called
+		/// The arguments to pass to the function.
+		/// 
+		/// The return value(s) of the function call.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, DynValue function, params object[] args)
+		{
+			DynValue[] dargs = new DynValue[args.Length];
+
+			for (int i = 0; i < dargs.Length; i++)
+				dargs[i] = DynValue.FromObject(this, args[i]);
+
+			return CallAsync(ecToken, function, dargs);
+		}
+
+
+
+		/// 
+		/// Asynchronously calls the specified function.
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The Lua/MoonSharp function to be called
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, object function)
+		{
+			return CallAsync(ecToken, DynValue.FromObject(this, function));
+		}
+
+
+		/// 
+		/// Asynchronously calls the specified function.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The execution control token to be associated with the execution of this function
+		/// The Lua/MoonSharp function to be called
+		/// The arguments to pass to the function.
+		/// 
+		/// Thrown if function is not of DataType.Function
+		public Task CallAsync(ExecutionControlToken ecToken, object function, params object[] args)
+		{
+			return CallAsync(ecToken, DynValue.FromObject(this, function), args);
+		}
+
+		/// 
+		/// Asynchronously creates a new dynamic expression.
+		/// 
+		/// This method is supported only on .NET 4.x and .NET 4.x PCL targets.
+		/// 
+		/// The code of the expression.
+		/// 
+		public Task CreateDynamicExpressionAsync(string code)
+		{
+			return Task.Factory.StartNew(() => CreateDynamicExpression(code));
+		}
+#endif
+
+
 		/// 
 		/// Creates a coroutine pointing at the specified function.
 		/// 
@@ -731,9 +981,9 @@ public DynamicExpression CreateConstantDynamicExpression(string code, DynValue c
 		/// those cases where the execution engine is not really running - for example for dynamic expression
 		/// or calls from CLR to CLR callbacks
 		/// 
-		internal ScriptExecutionContext CreateDynamicExecutionContext(CallbackFunction func = null)
+		internal ScriptExecutionContext CreateDynamicExecutionContext(ExecutionControlToken ecToken, CallbackFunction func = null)
 		{
-			return new ScriptExecutionContext(m_MainProcessor, func, null, isDynamic: true);
+			return new ScriptExecutionContext(ecToken, m_MainProcessor, func, null, isDynamic: true);
 		}
 
 		/// 
diff --git a/src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.net40-client/MoonSharp.Interpreter.net40-client.csproj b/src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.net40-client/MoonSharp.Interpreter.net40-client.csproj
index e5ea7555..d8144fd1 100755
--- a/src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.net40-client/MoonSharp.Interpreter.net40-client.csproj
+++ b/src/MoonSharp.Interpreter/_Projects/MoonSharp.Interpreter.net40-client/MoonSharp.Interpreter.net40-client.csproj
@@ -61,9 +61,6 @@
     
   
   
-    
-      AsyncExtensions.cs
-    
     
       AstNode.cs
     
@@ -817,6 +814,8 @@
     
       WhileStatement.cs
     
+    
+    
   
   
   
   
   
-    
-      AsyncExtensions.cs
-    
     
       AstNode.cs
     
@@ -814,6 +811,8 @@
     
       WhileStatement.cs
     
+    
+