Browse Source
Only use non-pumping synchronization context when handling WM_PAINT and taking the lock in WM_SIZEpull/5154/head
committed by
GitHub
9 changed files with 76 additions and 42 deletions
@ -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 |
|||
|
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Utilities |
|||
{ |
|||
public class NonPumpingLockHelper |
|||
{ |
|||
public interface IHelperImpl |
|||
{ |
|||
IDisposable Use(); |
|||
} |
|||
|
|||
public static IDisposable Use() => AvaloniaLocator.Current.GetService<IHelperImpl>()?.Use(); |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
using System; |
|||
using System.Runtime.ConstrainedExecution; |
|||
using System.Threading; |
|||
using Avalonia.Threading; |
|||
using Avalonia.Utilities; |
|||
using Avalonia.Win32.Interop; |
|||
|
|||
namespace Avalonia.Win32 |
|||
{ |
|||
internal class NonPumpingSyncContext : SynchronizationContext, IDisposable |
|||
{ |
|||
private readonly SynchronizationContext _inner; |
|||
|
|||
private NonPumpingSyncContext(SynchronizationContext inner) |
|||
{ |
|||
_inner = inner; |
|||
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() => SetSynchronizationContext(_inner); |
|||
|
|||
public static IDisposable Use() |
|||
{ |
|||
var current = Current; |
|||
if (current == null) |
|||
{ |
|||
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) |
|||
return null; |
|||
} |
|||
if (current is NonPumpingSyncContext) |
|||
return null; |
|||
|
|||
return new NonPumpingSyncContext(current); |
|||
} |
|||
|
|||
internal class HelperImpl : NonPumpingLockHelper.IHelperImpl |
|||
{ |
|||
IDisposable NonPumpingLockHelper.IHelperImpl.Use() => NonPumpingSyncContext.Use(); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue