OSDN Git Service

操作メニューの「タブ振り分けルール作成」から新規タブを作成するとエラーが発生する不具合を修正
[opentween/open-tween.git] / OpenTween / TimelineScheduler.cs
index 434d151..07648d8 100644 (file)
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -30,7 +31,7 @@ namespace OpenTween
 {
     public class TimelineScheduler
     {
-        private readonly Timer timer;
+        private readonly AsyncTimer timer;
 
         private bool enabled = false;
         private bool systemResumeMode = false;
@@ -78,6 +79,30 @@ namespace OpenTween
         public TimeSpan UpdateIntervalConfig { get; set; } = Timeout.InfiniteTimeSpan;
         public TimeSpan UpdateAfterSystemResume { get; set; } = Timeout.InfiniteTimeSpan;
 
+        public bool EnableUpdateHome
+            => this.UpdateIntervalHome != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateMention
+            => this.UpdateIntervalMention != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateDm
+            => this.UpdateIntervalDm != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdatePublicSearch
+            => this.UpdateIntervalPublicSearch != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateUser
+            => this.UpdateIntervalUser != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateList
+            => this.UpdateIntervalList != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateConfig
+            => this.UpdateIntervalConfig != Timeout.InfiniteTimeSpan;
+
+        public bool EnableUpdateSystemResume
+            => this.UpdateAfterSystemResume != Timeout.InfiniteTimeSpan;
+
         public Func<Task>? UpdateHome;
         public Func<Task>? UpdateMention;
         public Func<Task>? UpdateDm;
@@ -101,7 +126,7 @@ namespace OpenTween
         }
 
         public TimelineScheduler()
-            => this.timer = new Timer(_ => this.TimerCallback());
+            => this.timer = new AsyncTimer(this.TimerCallback);
 
         public void RefreshSchedule()
         {
@@ -116,12 +141,15 @@ namespace OpenTween
 
         public void SystemResumed()
         {
+            if (!this.EnableUpdateSystemResume)
+                return;
+
             this.SystemResumedAt = DateTimeUtc.Now;
             this.systemResumeMode = true;
             this.RefreshSchedule();
         }
 
-        private async void TimerCallback()
+        private async Task TimerCallback()
         {
             try
             {
@@ -145,33 +173,54 @@ namespace OpenTween
             var round = TimeSpan.FromSeconds(1); // 1秒未満の差異であればまとめて実行する
             var tasks = UpdateTask.None;
 
-            var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
-            if (nextScheduledHome - now < round)
-                tasks |= UpdateTask.Home;
+            if (this.EnableUpdateHome)
+            {
+                var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
+                if (nextScheduledHome - now < round)
+                    tasks |= UpdateTask.Home;
+            }
 
-            var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
-            if (nextScheduledMention - now < round)
-                tasks |= UpdateTask.Mention;
+            if (this.EnableUpdateMention)
+            {
+                var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
+                if (nextScheduledMention - now < round)
+                    tasks |= UpdateTask.Mention;
+            }
 
-            var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
-            if (nextScheduledDm - now < round)
-                tasks |= UpdateTask.Dm;
+            if (this.EnableUpdateDm)
+            {
+                var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
+                if (nextScheduledDm - now < round)
+                    tasks |= UpdateTask.Dm;
+            }
 
-            var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
-            if (nextScheduledPublicSearch - now < round)
-                tasks |= UpdateTask.PublicSearch;
+            if (this.EnableUpdatePublicSearch)
+            {
+                var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
+                if (nextScheduledPublicSearch - now < round)
+                    tasks |= UpdateTask.PublicSearch;
+            }
 
-            var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
-            if (nextScheduledUser - now < round)
-                tasks |= UpdateTask.User;
+            if (this.EnableUpdateUser)
+            {
+                var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
+                if (nextScheduledUser - now < round)
+                    tasks |= UpdateTask.User;
+            }
 
-            var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
-            if (nextScheduledList - now < round)
-                tasks |= UpdateTask.List;
+            if (this.EnableUpdateList)
+            {
+                var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
+                if (nextScheduledList - now < round)
+                    tasks |= UpdateTask.List;
+            }
 
-            var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
-            if (nextScheduledConfig - now < round)
-                tasks |= UpdateTask.Config;
+            if (this.EnableUpdateConfig)
+            {
+                var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
+                if (nextScheduledConfig - now < round)
+                    tasks |= UpdateTask.Config;
+            }
 
             await this.RunUpdateTasks(tasks, now).ConfigureAwait(false);
         }
@@ -191,61 +240,59 @@ namespace OpenTween
 
         private async Task RunUpdateTasks(UpdateTask tasks, DateTimeUtc now)
         {
-            var updateTasks = new List<Task>(capacity: 7);
-
-            // LastUpdate* を次の時刻に更新してから Update* を実行すること
-            // (LastUpdate* が更新されずに Update* が例外を投げると無限ループに陥る)
+            var updateTasks = new List<Func<Task>>(capacity: 7);
 
             if ((tasks & UpdateTask.Home) == UpdateTask.Home)
             {
                 this.LastUpdateHome = now;
                 if (this.UpdateHome != null)
-                    updateTasks.Add(this.UpdateHome());
+                    updateTasks.Add(this.UpdateHome);
             }
 
             if ((tasks & UpdateTask.Mention) == UpdateTask.Mention)
             {
                 this.LastUpdateMention = now;
                 if (this.UpdateMention != null)
-                    updateTasks.Add(this.UpdateMention());
+                    updateTasks.Add(this.UpdateMention);
             }
 
             if ((tasks & UpdateTask.Dm) == UpdateTask.Dm)
             {
                 this.LastUpdateDm = now;
                 if (this.UpdateDm != null)
-                    updateTasks.Add(this.UpdateDm());
+                    updateTasks.Add(this.UpdateDm);
             }
 
             if ((tasks & UpdateTask.PublicSearch) == UpdateTask.PublicSearch)
             {
                 this.LastUpdatePublicSearch = now;
                 if (this.UpdatePublicSearch != null)
-                    updateTasks.Add(this.UpdatePublicSearch());
+                    updateTasks.Add(this.UpdatePublicSearch);
             }
 
             if ((tasks & UpdateTask.User) == UpdateTask.User)
             {
                 this.LastUpdateUser = now;
                 if (this.UpdateUser != null)
-                    updateTasks.Add(this.UpdateUser());
+                    updateTasks.Add(this.UpdateUser);
             }
 
             if ((tasks & UpdateTask.List) == UpdateTask.List)
             {
                 this.LastUpdateList = now;
                 if (this.UpdateList != null)
-                    updateTasks.Add(this.UpdateList());
+                    updateTasks.Add(this.UpdateList);
             }
 
             if ((tasks & UpdateTask.Config) == UpdateTask.Config)
             {
                 this.LastUpdateConfig = now;
                 if (this.UpdateConfig != null)
-                    updateTasks.Add(this.UpdateConfig());
+                    updateTasks.Add(this.UpdateConfig);
             }
 
-            await Task.WhenAll(updateTasks).ConfigureAwait(false);
+            await Task.WhenAll(updateTasks.Select(x => Task.Run(x)))
+                .ConfigureAwait(false);
         }
 
         private TimeSpan NextTimerDelay()
@@ -264,33 +311,54 @@ namespace OpenTween
             // 次に更新が予定される時刻を判定する
             var min = DateTimeUtc.MaxValue;
 
-            var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
-            if (nextScheduledHome < min)
-                min = nextScheduledHome;
+            if (this.EnableUpdateHome)
+            {
+                var nextScheduledHome = this.LastUpdateHome + this.UpdateIntervalHome;
+                if (nextScheduledHome < min)
+                    min = nextScheduledHome;
+            }
 
-            var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
-            if (nextScheduledMention < min)
-                min = nextScheduledMention;
+            if (this.EnableUpdateMention)
+            {
+                var nextScheduledMention = this.LastUpdateMention + this.UpdateIntervalMention;
+                if (nextScheduledMention < min)
+                    min = nextScheduledMention;
+            }
 
-            var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
-            if (nextScheduledDm < min)
-                min = nextScheduledDm;
+            if (this.EnableUpdateDm)
+            {
+                var nextScheduledDm = this.LastUpdateDm + this.UpdateIntervalDm;
+                if (nextScheduledDm < min)
+                    min = nextScheduledDm;
+            }
 
-            var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
-            if (nextScheduledPublicSearch < min)
-                min = nextScheduledPublicSearch;
+            if (this.EnableUpdatePublicSearch)
+            {
+                var nextScheduledPublicSearch = this.LastUpdatePublicSearch + this.UpdateIntervalPublicSearch;
+                if (nextScheduledPublicSearch < min)
+                    min = nextScheduledPublicSearch;
+            }
 
-            var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
-            if (nextScheduledUser < min)
-                min = nextScheduledUser;
+            if (this.EnableUpdateUser)
+            {
+                var nextScheduledUser = this.LastUpdateUser + this.UpdateIntervalUser;
+                if (nextScheduledUser < min)
+                    min = nextScheduledUser;
+            }
 
-            var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
-            if (nextScheduledList < min)
-                min = nextScheduledList;
+            if (this.EnableUpdateList)
+            {
+                var nextScheduledList = this.LastUpdateList + this.UpdateIntervalList;
+                if (nextScheduledList < min)
+                    min = nextScheduledList;
+            }
 
-            var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
-            if (nextScheduledConfig < min)
-                min = nextScheduledConfig;
+            if (this.EnableUpdateConfig)
+            {
+                var nextScheduledConfig = this.LastUpdateConfig + this.UpdateIntervalConfig;
+                if (nextScheduledConfig < min)
+                    min = nextScheduledConfig;
+            }
 
             delay = min - DateTimeUtc.Now;