Это сложно. По нескольким причинам:
- Нельзя передать параметр с помощью
ref
методу async
. Вы используете await
, но для использования await
ваш метод должен быть отмечен async
. И async
методы не могут иметь ref
параметров. Например, это не скомпилирует:
async Task MethodAsync(ref bool isCancelled)
{
while (!isCancelled)
{
DoThis();
await DoTheNewThingAsync(isCancelled.ToCancellationToken());
DoThat();
}
}
Это приведет к ошибке компиляции:
CS1988: асинхронные методы не могут иметь параметры ref, in или out
Вы не можете использовать
ref
параметры в анонимных методах. Я думал об использовании
Timer
для проверки переменной. Примерно так:
public static CancellationToken ToCancellationToken(ref bool isCancelled)
{
var tokenSource = new CancellationTokenSource();
var timer = new System.Timers.Timer()
{
AutoReset = true,
Interval = 100
};
timer.Elapsed += (source, e) =>
{
if (isCancelled)
{
tokenSource.Cancel();
timer.Dispose();
}
};
timer.Enabled = true;
return tokenSource.Token;
}
Но это дает вам ошибку компилятора:
CS1628: Невозможно использовать ref, out или в параметре isCancelled внутри анонимногометод, лямбда-выражение, выражение запроса или локальная функция
Я не вижу другого способа получить bool
в обработчике событий по ссылке.
Самое близкое, что я мог бы получить, это что-то вроде этого:
void Method(ref bool isCancelled)
{
while (!isCancelled)
{
DoThis();
using (var tokenSource = new CancellationTokenSource()) {
var mytask = DoTheNewThingAsync(tokenSource.Token);
while (true)
{
//wait for either the task to finish, or 100ms
if (Task.WaitAny(mytask, Task.Delay(100)) == 0)
{
break; //mytask finished
}
if (isCancelled) tokenSource.Cancel();
}
// This will throw an exception if an exception happened in
// DoTheNewThingAsync. Otherwise we'd never know if it
// completed successfully or not.
mytask.GetAwaiter().GetResult();
}
DoThat();
}
}
Однако это блокирует вызывающего, поэтому я не совсем понимаю, как это может быть даже полезно (как это может сделать вызывающий)измените isCancelled
, если он заблокирован?). Но это похоже на то, что делает ваш существующий метод, так что, возможно, он будет работать?
Но это супер хакерский. Если вы вообще можете контролировать, как что-либо делается вверх по течению, сделайте это вместо этого.