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: |
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. |
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.Logging.DebugLogSink' 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 |
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