Skip to content

Commit b0352ac

Browse files
committed
Add RegisterWaitForSingleObjectAsync.
1 parent c9aa66b commit b0352ac

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

src/AsyncFiberWorks/Threading/ThreadPoolExtensions.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,33 @@ public static async Task QueueAsync(this IThreadPool threadPool, Action action)
4545
{
4646
await threadPool.QueueAsync((_) => action()).ConfigureAwait(false);
4747
}
48+
49+
/// <summary>
50+
/// Wait for WaitHandle.
51+
/// </summary>
52+
/// <param name="threadPool">Thread pool used for waiting.</param>
53+
/// <param name="waitHandle">Waiting target.</param>
54+
/// <param name="cancellationToken">Handle for cancellation.</param>
55+
/// <returns>Task waiting for WaitHandle to complete.</returns>
56+
/// <exception cref="OperationCanceledException">An exception that occurs when canceled.</exception>
57+
public static async Task RegisterWaitForSingleObjectAsync(this IThreadPool threadPool, WaitHandle waitHandle, CancellationToken cancellationToken)
58+
{
59+
await threadPool.QueueAsync(() =>
60+
{
61+
int index = WaitHandle.WaitAny(new WaitHandle[]
62+
{
63+
waitHandle,
64+
cancellationToken.WaitHandle
65+
});
66+
if (index == 0)
67+
{
68+
// completed.
69+
}
70+
else
71+
{
72+
cancellationToken.ThrowIfCancellationRequested();
73+
}
74+
}).ConfigureAwait(false);
75+
}
4876
}
4977
}

src/AsyncFiberWorksTests/ThreadPoolTests.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ public class ThreadPoolTests
1616
{
1717
static int NumberOfMinThreads = 2;
1818

19+
static object[] ThreadPoolCreators =
20+
{
21+
new object[] { (Func<IThreadPool>)(() => DefaultThreadPool.Instance) },
22+
new object[] { (Func<IThreadPool>)(() => UserThreadPool.StartNew(3)) },
23+
};
24+
1925
[OneTimeSetUp]
2026
public void Init()
2127
{
@@ -226,12 +232,33 @@ public async Task ThreadPoolQueueAsync(Func<IThreadPool> poolCreator)
226232
Assert.AreEqual(201, value);
227233
}
228234

229-
230-
static object[] ThreadPoolCreators =
235+
[Test, TestCaseSource(nameof(ThreadPoolCreators))]
236+
public async Task ThreadPoolRegisterWaitForSingleObjectAsyncTest(Func<IThreadPool> poolCreator)
231237
{
232-
new object[] { (Func<IThreadPool>)(() => DefaultThreadPool.Instance) },
233-
new object[] { (Func<IThreadPool>)(() => UserThreadPool.StartNew(3)) },
234-
};
238+
var threadPool = poolCreator();
239+
var cts = new CancellationTokenSource();
240+
var manualResetEvent1 = new ManualResetEventSlim();
241+
var t1 = threadPool.RegisterWaitForSingleObjectAsync(manualResetEvent1.WaitHandle, cts.Token);
242+
Assert.IsFalse(t1.IsCompleted);
243+
244+
manualResetEvent1.Set();
245+
await t1.ConfigureAwait(false);
246+
Assert.IsTrue(t1.IsCompleted);
235247

248+
var manualResetEvent2 = new ManualResetEventSlim();
249+
var t2 = threadPool.RegisterWaitForSingleObjectAsync(manualResetEvent2.WaitHandle, cts.Token);
250+
Assert.IsFalse(t2.IsCompleted);
251+
252+
cts.Cancel();
253+
try
254+
{
255+
await t2.ConfigureAwait(false);
256+
}
257+
catch (OperationCanceledException)
258+
{
259+
}
260+
Assert.IsTrue(t2.IsCompleted);
261+
Assert.IsTrue(t2.IsCanceled);
262+
}
236263
}
237264
}

0 commit comments

Comments
 (0)