Forráskód Böngészése

Avoid lock in timers

ili 3 éve
szülő
commit
ee662cecdd

+ 16 - 29
src/Android/Avalonia.Android/AndroidThreadingInterface.cs

@@ -27,46 +27,33 @@ namespace Avalonia.Android
         {
             if (interval.TotalMilliseconds < 10)
                 interval = TimeSpan.FromMilliseconds(10);
-            object l = new object();
+
             var stopped = false;
             Timer timer = null;
-            var scheduled = false;
             timer = new Timer(_ =>
             {
-                lock (l)
+                if (stopped)
+                    return;
+
+                EnsureInvokeOnMainThread(() =>
                 {
-                    if (stopped)
+                    try
                     {
-                        timer.Dispose();
-                        return;
+                        tick();
                     }
-                    if (scheduled)
-                        return;
-                    scheduled = true;
-                    EnsureInvokeOnMainThread(() =>
+                    finally
                     {
-                        try
-                        {
-                            tick();
-                        }
-                        finally
-                        {
-                            lock (l)
-                            {
-                                scheduled = false;
-                            }
-                        }
-                    });
-                }
-            }, null, TimeSpan.Zero, interval);
+                        if (!stopped)
+                            timer.Change(interval, Timeout.InfiniteTimeSpan);
+                    }
+                });
+            },
+            null, interval, Timeout.InfiniteTimeSpan);
 
             return Disposable.Create(() =>
             {
-                lock (l)
-                {
-                    stopped = true;
-                    timer.Dispose();
-                }
+                stopped = true;
+                timer.Dispose();
             });
         }
 

+ 2 - 2
src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs

@@ -43,7 +43,7 @@ namespace Avalonia.Controls.Platform
                 _priority = priority;
                 _interval = interval;
                 _tick = tick;
-                _timer = new Timer(OnTimer, null, interval, TimeSpan.FromMilliseconds(-1));
+                _timer = new Timer(OnTimer, null, interval, Timeout.InfiniteTimeSpan);
                 _handle = GCHandle.Alloc(_timer);
             }
 
@@ -57,7 +57,7 @@ namespace Avalonia.Controls.Platform
                     if (_timer == null)
                         return;
                     _tick();
-                    _timer?.Change(_interval, TimeSpan.FromMilliseconds(-1));
+                    _timer?.Change(_interval, Timeout.InfiniteTimeSpan);
                 });
             }
 

+ 24 - 24
src/Avalonia.Headless/HeadlessPlatformThreadingInterface.cs

@@ -36,35 +36,35 @@ namespace Avalonia.Headless
 
         public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
         {
-            var cancelled = false;
-            var enqueued = false;
-            var l = new object();
-            var timer = new Timer(_ =>
+            if (interval.TotalMilliseconds < 10)
+                interval = TimeSpan.FromMilliseconds(10);
+
+            var stopped = false;
+            Timer timer = null;
+            timer = new Timer(_ =>
             {
-                lock (l)
+                if (stopped)
+                    return;
+
+                Dispatcher.UIThread.Post(() =>
                 {
-                    if (cancelled || enqueued)
-                        return;
-                    enqueued = true;
-                    Dispatcher.UIThread.Post(() =>
+                    try
                     {
-                        lock (l)
-                        {
-                            enqueued = false;
-                            if (cancelled)
-                                return;
-                            tick();
-                        }
-                    }, priority);
-                }
-            }, null, interval, interval);
+                        tick();
+                    }
+                    finally
+                    {
+                        if (!stopped)
+                            timer.Change(interval, Timeout.InfiniteTimeSpan);
+                    }
+                });
+            },
+            null, interval, Timeout.InfiniteTimeSpan);
+
             return Disposable.Create(() =>
             {
-                lock (l)
-                {
-                    timer.Dispose();
-                    cancelled = true;
-                }
+                stopped = true;
+                timer.Dispose();
             });
         }