Вам нужно передать токен отмены. Где-то за пределами этого кода вам нужно создать CancellationTokenSource
, лучшее место, вероятно, это свойство вида:
class MainForm
{
CancellationTokenSource cts;
...
Затем вы инициализируете это и передайте это Start()
:
private async void MainForm_Shown(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
await Start(ct);
}
При запуске l oop вам необходимо отслеживать токен отмены:
Поскольку вы используете задержку для тайм-аута ConnectAsync()
вам нужно Task.Delay()
, чтобы знать, когда запрашивается отмена, поэтому вам нужно передать токен в Task.Delay ():
await Task.WhenAny(ca, Task.Delay(sendTimeDevice,ct));
После TcpClient.Close()
вам нужно проверить, запрашивается ли отмена и остановите циклы, если это:
if (ct.IsCancellationRequested)
break;
Вам нужно будет выполнить тот же тест в while loop
, а также выполнить его непосредственно перед ConnectAsync()
. Хотя наиболее вероятное место, с которым вы столкнетесь ct.IsCancellationRequested == true
, будет сразу после Task.WhenyAny
или сразу после интервала L oop, нет смысла начинать ConnectAsync()
, если была запрошена отмена.
Вы должны также передайте CancellationToken с интервалом L oop, в противном случае вы можете ждать interval
до закрытия формы:
// This will throw an OperationCancelled Exception if it is cancelled.
await Task.Delay(interval,ct);
Потому что вы все равно продолжите и просто выйдите, если отменено зарегистрировано Вы могли бы избежать написания отдельной попытки / захвата, которая ничего не делает и ожидает такой интервал, он почти наверняка менее эффективен, но он чище.
// Leave any exceptions of Task.Delay() unobserved and continue
await Task.WhenAny(Task.Delay(interval,ct));
Наконец, вам нужно избавиться от CancellationTokenSource, я полагаю, вы будет делать это в чем-то вроде MainForm_Closed()
функции?
private void MainForm_Closed(object sender, EventArgs e)
{
cts.Dispose();
Единственное, что остается сделать, это работать, когда вы хотите запустить запрос CancellationRequest, основываясь на том, что вы сказали, что хотите сделать это когда кнопка закрытия формы была нажата, так:
private void MainForm_Closing(object sender, EventArgs e)
{
cts.Cancel();
Это приведет к отмене Если вы переходите в отмененное состояние, ваша подпрограмма Start()
увидит это и выйдет.
В вашем коде нет единого места для проверки установки CancellationToken, эмпирическое правило - проверять его до и после любого await
, и в вашем случае вы должны проверить его как в while
, так и в for
l oop.