В моем текущем проекте у меня есть кусок кода, который после упрощения до проблем, где я нахожусь, выглядит примерно так:
private async Task RunAsync(CancellationToken cancel)
{
bool finished = false;
while (!cancel.IsCancellationRequested && !finished)
finished = await FakeTask();
}
private Task<bool> FakeTask()
{
return Task.FromResult(false);
}
Если я использую этот код без ожидания,В конце концов я блокирую:
// example 1
var task = RunAsync(cancel); // Code blocks here...
... // Other code that could run while RunAsync is doing its thing, but is forced to wait
await task;
// example 2
var task = RunAsync(cancelSource.Token); // Code blocks here...
cancelSource.Cancel(); // Never called
В реальном проекте я фактически не использую FakeTask, и обычно там будет некоторое Task.Delay, которого я жду там, так что код большей части кодавремя фактически не блокируется, или только для ограниченного количества итераций.
Однако в модульном тестировании я использую фиктивный объект, который в значительной степени выполняет то же, что и FakeTask, поэтому, когда я хочу увидетьесли RunAsync реагирует на отмену отмены CancellationToken так, как я этого ожидаю, я застрял.
Я обнаружил, что могу решить эту проблему, добавив, например, await Task.Delay(1)
вверху RunAsync, чтобы принудительно вызвать его.чтобы действительно работать асинхронно, но это кажется немного хакерским.Есть ли лучшие альтернативы?