From 2d5999990a6959b70b2ae1fc548237d586a2c7ec Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 7 Dec 2020 21:02:19 +0300 Subject: [PATCH] Use non-alertable waits only for WM_PAINT handling --- src/Avalonia.Base/ApiCompatBaseline.txt | 4 +-- .../AvaloniaSynchronizationContext.cs | 25 ++------------ src/Avalonia.FreeDesktop/DBusHelper.cs | 2 +- .../Avalonia.Win32/NonPumpingSyncContext.cs | 34 +++++++++++++++++++ .../Avalonia.Win32/NonPumpingWaitProvider.cs | 15 -------- src/Windows/Avalonia.Win32/Win32Platform.cs | 1 - .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 1 + 7 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs delete mode 100644 src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs diff --git a/src/Avalonia.Base/ApiCompatBaseline.txt b/src/Avalonia.Base/ApiCompatBaseline.txt index 5d19373a92..d17f25ec49 100644 --- a/src/Avalonia.Base/ApiCompatBaseline.txt +++ b/src/Avalonia.Base/ApiCompatBaseline.txt @@ -1,4 +1,4 @@ Compat issues with assembly Avalonia.Base: -CannotAddAbstractMembers : Member 'protected System.IObservable Avalonia.AvaloniaProperty.GetChanged()' is abstract in the implementation but is missing in the contract. -TypesMustExist : Type 'Avalonia.Logging.DebugLogSink' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void Avalonia.Threading.AvaloniaSynchronizationContext..ctor(Avalonia.Threading.AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider)' does not exist in the implementation but it does exist in the contract. +TypesMustExist : Type 'Avalonia.Threading.AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider' does not exist in the implementation but it does exist in the contract. Total Issues: 2 diff --git a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs index 40cf81358f..1a78792173 100644 --- a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs +++ b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs @@ -9,20 +9,6 @@ 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. /// @@ -38,8 +24,7 @@ namespace Avalonia.Threading return; } - SetSynchronizationContext(new AvaloniaSynchronizationContext(AvaloniaLocator.Current - .GetService())); + SetSynchronizationContext(new AvaloniaSynchronizationContext()); } /// @@ -57,12 +42,6 @@ namespace Avalonia.Threading 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 91c4c28995..b445f86613 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(null); + _ctx = new AvaloniaSynchronizationContext(); } } public static Connection Connection { get; private set; } diff --git a/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs new file mode 100644 index 0000000000..ab35b04b7a --- /dev/null +++ b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.ConstrainedExecution; +using System.Threading; +using Avalonia.Threading; +using Avalonia.Win32.Interop; + +namespace Avalonia.Win32 +{ + internal class NonPumpingSyncContext : SynchronizationContext, IDisposable + { + private readonly SynchronizationContext _inner; + + private NonPumpingSyncContext() + { + _inner = Current; + SetWaitNotificationRequired(); + SetSynchronizationContext(this); + } + + public override void Post(SendOrPostCallback d, object state) => _inner.Post(d, state); + public override void Send(SendOrPostCallback d, object state) => _inner.Send(d, state); + + [PrePrepareMethod] + public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) + { + return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll, + millisecondsTimeout, false); + } + + public void Dispose() => SynchronizationContext.SetSynchronizationContext(_inner); + + public static IDisposable Use() => new NonPumpingSyncContext(); + } +} diff --git a/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs b/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs deleted file mode 100644 index a0160fcfbd..0000000000 --- a/src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -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 5b16cae26e..c205faefdd 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -110,7 +110,6 @@ namespace Avalonia.Win32 .Bind().ToConstant(s_instance) .Bind().ToSingleton() .Bind().ToConstant(s_instance) - .Bind().ToConstant(new NonPumpingWaitProvider()) .Bind().ToConstant(new WindowsMountedVolumeInfoProvider()); Win32GlManager.Initialize(); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 78de681403..61af3efd73 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -348,6 +348,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_PAINT: { + using(NonPumpingSyncContext.Use()) using (_rendererLock.Lock()) { if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)