Browse Source

Use non-alertable waits only for WM_PAINT handling

pull/5149/head
Nikita Tsukanov 5 years ago
parent
commit
2d5999990a
  1. 4
      src/Avalonia.Base/ApiCompatBaseline.txt
  2. 25
      src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
  3. 2
      src/Avalonia.FreeDesktop/DBusHelper.cs
  4. 34
      src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs
  5. 15
      src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
  6. 1
      src/Windows/Avalonia.Win32/Win32Platform.cs
  7. 1
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

4
src/Avalonia.Base/ApiCompatBaseline.txt

@ -1,4 +1,4 @@
Compat issues with assembly Avalonia.Base:
CannotAddAbstractMembers : Member 'protected System.IObservable<Avalonia.AvaloniaPropertyChangedEventArgs> 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

25
src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs

@ -9,20 +9,6 @@ namespace Avalonia.Threading
/// </summary>
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();
}
/// <summary>
/// Controls if SynchronizationContext should be installed in InstallIfNeeded. Used by Designer.
/// </summary>
@ -38,8 +24,7 @@ namespace Avalonia.Threading
return;
}
SetSynchronizationContext(new AvaloniaSynchronizationContext(AvaloniaLocator.Current
.GetService<INonPumpingPlatformWaitProvider>()));
SetSynchronizationContext(new AvaloniaSynchronizationContext());
}
/// <inheritdoc/>
@ -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);
}
}
}

2
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; }

34
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();
}
}

15
src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs

@ -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);
}
}
}

1
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -110,7 +110,6 @@ namespace Avalonia.Win32
.Bind<IWindowingPlatform>().ToConstant(s_instance)
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
.Bind<IPlatformIconLoader>().ToConstant(s_instance)
.Bind<AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider>().ToConstant(new NonPumpingWaitProvider())
.Bind<IMountedVolumeInfoProvider>().ToConstant(new WindowsMountedVolumeInfoProvider());
Win32GlManager.Initialize();

1
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)

Loading…
Cancel
Save