'How to correctly wait for callback with timeout fallback
I am testing web socket subscriptions in my tests and I would like to wait for response from callback and then end the test, if no response is received after timeout end the test.
This is what I have now (simplified) but I am not sure if its the way how to do it.
public async Task WaitForPing()
{
var cancellationTokenSource = new CancellationTokenSource(5_000);
var pinged = false;
using var _ = Client.OnPing(_ =>
{
pinged = true;
cancellationTokenSource.Cancel();
}
await Client.Run();
await Task
.Delay(-1, cancellationTokenSource.Token)
.ContinueWith(_ => { }, CancellationToken.None);
Assert(pinged);
}
Solution 1:[1]
A proper method should be like that:
static Task<string> WaitForResponseAsync(CancellationTokenSource cancellationTokenSource = default)
{
var tcs = new TaskCompletionSource<string>();
// Register a method that throws an exception when task cancelled.
cancellationTokenSource.Token.Register(()=> throw new Exception("Timed out!"));
// Replace this task with your async operation. Like OnPing(_ => ...
Task.Run(async () =>
{
await Task.Delay(30_000); // Response will be received after 30 seconds
tcs.SetResult("Hello World");
});
return tcs.Task; // Return awaitable task
}
And place where you call that method:
try
{
Console.WriteLine(await WaitForResponseAsync(new CancellationTokenSource(5_000))); // Time out is 5 seconds
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Don't worry about the task in a task, you should replace it with your event. So if I customize it according to your method, it should be something like that:
Task WaitForPing(CancellationTokenSource cancellationTokenSource)
{
var tcs = new TaskCompletionSource();
cancellationTokenSource.Token.Register(() => throw new Exception("Timed out"));
// Or just call SetResult to finish the task before completed without exception:
// cancellationTokenSource.Token.Register(() => tcs.SetResult());
// (Personally I do not recommend this one)
using var _ = Client.OnPing(_ =>
{
tcs.SetResult();
};
return tcs.Task;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | enisn |
