diff --git a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
index 38a23f918f..40cf81358f 100644
--- a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
+++ b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Runtime.ConstrainedExecution;
using System.Threading;
namespace Avalonia.Threading
@@ -7,6 +9,20 @@ namespace Avalonia.Threading
///
public class AvaloniaSynchronizationContext : SynchronizationContext
{
+ public interface INonPumpingPlatformWaitProvider
+ {
+ int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
+ }
+
+ private readonly INonPumpingPlatformWaitProvider _waitProvider;
+
+ public AvaloniaSynchronizationContext(INonPumpingPlatformWaitProvider waitProvider)
+ {
+ _waitProvider = waitProvider;
+ if (_waitProvider != null)
+ SetWaitNotificationRequired();
+ }
+
///
/// Controls if SynchronizationContext should be installed in InstallIfNeeded. Used by Designer.
///
@@ -22,7 +38,8 @@ namespace Avalonia.Threading
return;
}
- SetSynchronizationContext(new AvaloniaSynchronizationContext());
+ SetSynchronizationContext(new AvaloniaSynchronizationContext(AvaloniaLocator.Current
+ .GetService()));
}
///
@@ -39,5 +56,13 @@ namespace Avalonia.Threading
else
Dispatcher.UIThread.InvokeAsync(() => d(state), DispatcherPriority.Send).Wait();
}
+
+ [PrePrepareMethod]
+ public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+ {
+ if (_waitProvider != null)
+ return _waitProvider.Wait(waitHandles, waitAll, millisecondsTimeout);
+ return base.Wait(waitHandles, waitAll, millisecondsTimeout);
+ }
}
}
diff --git a/src/Avalonia.FreeDesktop/DBusHelper.cs b/src/Avalonia.FreeDesktop/DBusHelper.cs
index b445f86613..91c4c28995 100644
--- a/src/Avalonia.FreeDesktop/DBusHelper.cs
+++ b/src/Avalonia.FreeDesktop/DBusHelper.cs
@@ -43,7 +43,7 @@ namespace Avalonia.FreeDesktop
public void Initialized()
{
lock (_lock)
- _ctx = new AvaloniaSynchronizationContext();
+ _ctx = new AvaloniaSynchronizationContext(null);
}
}
public static Connection Connection { get; private set; }
diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
index 1aec4f0016..392ca31282 100644
--- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
+++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -1382,6 +1383,22 @@ namespace Avalonia.Win32.Interop
throw new Exception("RtlGetVersion failed!");
}
}
+
+ [DllImport("kernel32", EntryPoint="WaitForMultipleObjectsEx", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern int IntWaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable);
+
+ public const int WAIT_FAILED = unchecked((int)0xFFFFFFFF);
+
+ internal static int WaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable)
+ {
+ int result = IntWaitForMultipleObjectsEx(nCount, pHandles, bWaitAll, dwMilliseconds, bAlertable);
+ if(result == WAIT_FAILED)
+ {
+ throw new Win32Exception();
+ }
+
+ return result;
+ }
[DllImport("user32.dll")]
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
diff --git a/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs b/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
new file mode 100644
index 0000000000..a0160fcfbd
--- /dev/null
+++ b/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
@@ -0,0 +1,15 @@
+using System;
+using Avalonia.Threading;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32
+{
+ internal class NonPumpingWaitProvider : AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider
+ {
+ public int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+ {
+ return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll,
+ millisecondsTimeout, false);
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs
index b7bb0e19ba..af6058d197 100644
--- a/src/Windows/Avalonia.Win32/Win32Platform.cs
+++ b/src/Windows/Avalonia.Win32/Win32Platform.cs
@@ -93,6 +93,7 @@ namespace Avalonia.Win32
.Bind().ToConstant(s_instance)
.Bind().ToSingleton()
.Bind().ToConstant(s_instance)
+ .Bind().ToConstant(new NonPumpingWaitProvider())
.Bind().ToConstant(new WindowsMountedVolumeInfoProvider());
if (options.AllowEglInitialization)