teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

コードの更新

2016/12/13 11:49

投稿

tamoto
tamoto

スコア4333

answer CHANGED
@@ -15,8 +15,10 @@
15
15
  スケジューラーに処理を登録(予約)すると、スケジューラーがそれを勝手に順次実行していくので、使用者側では定期的に処理をスケジューラーに投げるだけでよくなります。
16
16
 
17
17
  お節介ですが、ちょうど少し前に似たような問題に適用できるスケジューラーの汎用実装を作ったものがあったので、もしよろしければこちらをお使いください。(100行くらいあるけど回答欄に貼ってもいいんですかね……?)
18
+
18
- もし意図に沿っていない場合は、ここ以下は読み飛ばして結構です。
19
+ (12/13 コードを更新)
19
20
  ```csharp
21
+
20
22
  public class ActionQueueScheduler
21
23
  {
22
24
  private readonly ConcurrentQueue<Func<Task>> queue;
@@ -70,7 +72,7 @@
70
72
 
71
73
  public Task Interrupt(Func<Task> action)
72
74
  => this.Interrupt(async () => { await action(); return default(object); });
73
-
75
+
74
76
  public Task<T> Interrupt<T>(Func<Task<T>> action)
75
77
  {
76
78
  var tcs = new TaskCompletionSource<T>();
@@ -94,7 +96,7 @@
94
96
  {
95
97
  tcs.TrySetException(exception);
96
98
  }
97
- return Task.CompletedTask;
99
+ return Task.FromResult(default(object));
98
100
  }
99
101
 
100
102
  private async Task CreateTaskAsync<T>(Func<Task<T>> asyncAction, TaskCompletionSource<T> tcs)
@@ -115,12 +117,12 @@
115
117
  return;
116
118
  Task.Run(async () =>
117
119
  {
120
+ var action = default(Func<Task>);
118
121
  while (true)
119
122
  {
120
123
  if (this.immediate != null)
121
- await (Interlocked.Exchange(ref this.immediate, null)?.Invoke().ConfigureAwait(false)
124
+ await Interlocked.Exchange(ref this.immediate, null).Invoke().ConfigureAwait(false);
122
- ?? Task.CompletedTask.ConfigureAwait(false));
123
- else if (this.queue.TryDequeue(out var action))
125
+ else if (this.queue.TryDequeue(out action))
124
126
  await action().ConfigureAwait(false);
125
127
  else
126
128
  break;