Имея этот обработчик:
public async Task<Result> Handle(MyQuery request, CancellationToken cancellationToken)
{
var cancellationTokenSource = new CancellationTokenSource();
await Parallel.ForEachAsync(myList, async (objectId, _) =>
{
var result = await _service.GetObject(objectId);
if (result.Any())
{
cancellationTokenSource.Cancel();
}
});
if (cancellationTokenSource.IsCancellationRequested) return Result.Fail("Error message.");
return Result.Ok();
}
Это работает, но мне интересно, правильно ли я использую CancellationTokenSource?
Если он обнаружит, что запись существует в result, необходимо вернуть Result.Fail(""); и остановить цикл.
Если вам нужно остановить цикл, вы должны передать cancellationTokenSource.Token соответствующей перегрузке ForEachAsync(). Затем вам нужно будет поймать OperationCanceledException вне цикла.
Ваша текущая реализация не остановит цикл.





Вы используете CancellationTokenSource просто как логическую переменную. Если цель состоит в том, чтобы отменить пакет при выполнении некоторого условия, то использование совершенно неправильное, вам нужно передать токен в вызов ForEachAsync (и в идеале обработать токен отмены в теле). Что-то в этом роде:
try
{
await Parallel.ForEachAsync(myList, cancellationTokenSource.Token, async (objectId, ct) =>
{
// pass the cancellation token
var result = await _service.GetObject(objectId, ct);
if (result.Any())
{
cancellationTokenSource.Cancel();
}
});
}
catch (OperationCanceledException e)
{
Result.Fail("Error message.");
}
И как правильно отмечает @Magnus - вам также следует использовать токен отмены, переданный в ваш метод Handle (CancellationToken cancellationToken):
using var cancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
// ...
Смотрите также:
И наверное хорошая идея совместить это с входящим кт. var cts = CancellationTokenSource.CreateLinkedToken(cancellationToken)
Какова цель этого кода? Если вам нужно сообщить, что какая-либо из итераций имеет «result.Any()», просто установите логическую переменную.