diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj
index 65c2a75b1c..1a2bdeef1e 100644
--- a/src/Avalonia.Native/Avalonia.Native.csproj
+++ b/src/Avalonia.Native/Avalonia.Native.csproj
@@ -19,8 +19,9 @@
-
-
+
+
+
diff --git a/src/Avalonia.Native/CallbackBase.cs b/src/Avalonia.Native/CallbackBase.cs
index 67c383f6ae..1356dd58ff 100644
--- a/src/Avalonia.Native/CallbackBase.cs
+++ b/src/Avalonia.Native/CallbackBase.cs
@@ -2,11 +2,13 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Runtime.ExceptionServices;
using SharpGen.Runtime;
+using Avalonia.Platform;
namespace Avalonia.Native
{
- public class CallbackBase : SharpGen.Runtime.IUnknown
+ public class CallbackBase : SharpGen.Runtime.IUnknown, IExceptionCallback
{
private uint _refCount;
private bool _disposed;
@@ -76,5 +78,15 @@ namespace Avalonia.Native
{
}
+
+ public void RaiseException(Exception e)
+ {
+ if (AvaloniaLocator.Current.GetService() is PlatformThreadingInterface threadingInterface)
+ {
+ threadingInterface.TerminateNativeApp();
+
+ threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e));
+ }
+ }
}
}
diff --git a/src/Avalonia.Native/PlatformThreadingInterface.cs b/src/Avalonia.Native/PlatformThreadingInterface.cs
index 353124a9d1..5ddaf83ed4 100644
--- a/src/Avalonia.Native/PlatformThreadingInterface.cs
+++ b/src/Avalonia.Native/PlatformThreadingInterface.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Runtime.ExceptionServices;
using System.Threading;
using Avalonia.Native.Interop;
using Avalonia.Platform;
@@ -43,6 +44,8 @@ namespace Avalonia.Native
}
readonly IAvnPlatformThreadingInterface _native;
+ private ExceptionDispatchInfo _exceptionDispatchInfo;
+ private CancellationTokenSource _exceptionCancellationSource;
public PlatformThreadingInterface(IAvnPlatformThreadingInterface native)
{
@@ -57,32 +60,48 @@ namespace Avalonia.Native
public void RunLoop(CancellationToken cancellationToken)
{
- if (cancellationToken.CanBeCanceled == false)
- _native.RunLoop(null);
- else
+ var l = new object();
+ _exceptionCancellationSource = new CancellationTokenSource();
+
+ var compositeCancellation = CancellationTokenSource
+ .CreateLinkedTokenSource(cancellationToken, _exceptionCancellationSource.Token).Token;
+
+ var cancellation = _native.CreateLoopCancellation();
+ compositeCancellation.Register(() =>
{
- var l = new object();
- var cancellation = _native.CreateLoopCancellation();
- cancellationToken.Register(() =>
+ lock (l)
{
- lock (l)
- {
- cancellation?.Cancel();
- }
- });
- try
- {
- _native.RunLoop(cancellation);
+ cancellation?.Cancel();
}
- finally
+ });
+
+ try
+ {
+ _native.RunLoop(cancellation);
+ }
+ finally
+ {
+ lock (l)
{
- lock(l)
- {
- cancellation?.Dispose();
- cancellation = null;
- }
+ cancellation?.Dispose();
+ cancellation = null;
}
}
+
+ if (_exceptionDispatchInfo != null)
+ {
+ _exceptionDispatchInfo.Throw();
+ }
+ }
+
+ public void DispatchException (ExceptionDispatchInfo exceptionInfo)
+ {
+ _exceptionDispatchInfo = exceptionInfo;
+ }
+
+ public void TerminateNativeApp()
+ {
+ _exceptionCancellationSource?.Cancel();
}
public void Signal(DispatcherPriority priority)