回答編集履歴
1
コードの更新
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.
|
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
|
124
|
+
await Interlocked.Exchange(ref this.immediate, null).Invoke().ConfigureAwait(false);
|
122
|
-
?? Task.CompletedTask.ConfigureAwait(false));
|
123
|
-
else if (this.queue.TryDequeue(out
|
125
|
+
else if (this.queue.TryDequeue(out action))
|
124
126
|
await action().ConfigureAwait(false);
|
125
127
|
else
|
126
128
|
break;
|