у меня такой код
public async Task DoStuff()
{
_client.Ready += () => client_Ready("test");
await Task.Delay(-1);
}
private async Task client_Ready(string message)
{
await _client.SendMessageAsync(message);
}
как я могу сказать, что после того, как client_Ready
вызывается один раз, весь DoStuff
должен завершиться/выполнить возврат вместо ожидания?
Есть ли «хороший» способ сделать это, или мне нужно поработать, например, создать исключение и поймать его «выше»?
МРЭ:
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task RandomlyDelayedStuff()
{
Console.WriteLine("this ended");
await Task.Delay(200);
}
public static async Task DoStuff()
{
var rnd = new Random();
await Task.Delay(rnd.Next(0, 5000)).ContinueWith(async task =>
{
await RandomlyDelayedStuff();
});
await Task.Delay(-1);
}
public static async Task Main()
{
await DoStuff();
Console.WriteLine("ended");
}
}
Я не понимаю вопроса. Вы говорите: «Я не хочу DoStuff
возвращаться, пока client_Ready
не завершит выполнение»? Если да - зачем тебе это?
Пожалуйста, поделитесь минимально воспроизводимым примером.
@mjwills Я подключаюсь к client
, который через некоторое время X
возвращает мне ответ и вызывает Ready
(метод client_Ready
). Я использовал Task.Delay(-1)
, поэтому программа не выходит из функции DoStuff
мгновенно (до того, как я получил Ready
). Проблема в том, что он никогда не покидает его даже после того, как событие было вызвано
Да, пожалуйста, предоставьте MRE, потому что эта часть необходимости «не выходить DoStuff
» не имеет для меня смысла. Вы назначили обработчик события, вам просто нужно, чтобы обработчик был вызван, я не понимаю, почему это проблема, которая DoStuff
сразу заканчивается.
Вы создаете задачу и просите ее ждать бесконечно. Вы имели в виду применить это к задаче, возвращенной client_Ready
, которую вы сейчас игнорируете?
Вероятно, вы захотите использовать TaskCompletionSource здесь dotnetfiddle.net/gnfH5C
Используйте токен отмены. Передайте токен вызову задержки. Вы можете создать CancellationTokenSource и вызвать для него отмену, которая инициирует отмену вызова для токена.
CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
public async Task DoStuff()
{
_client.Ready += () => client_Ready("test");
await Task.Delay(-1, cancelTokenSource.Token);
// do something else here if desired
}
private async Task client_Ready(string message)
{
await _client.SendMessageAsync(message);
cancelTokenSource.Cancel();
}
Вы должны быть в состоянии сделать это с помощью токена отмены.
Код не проверен, я сделал это с задержкой и с помощью отмены для сброса, но никогда с бесконечным таймером и отменой.
const int cDelayMS = -1;
private System.Threading.CancellationTokenSource mCancel = new();
DoStuff()
{
Task.Delay(cDelayMS, mCancel.Token).ContinueWith(
async antecedent =>
{
if (antecedent.Status == TaskStatus.Canceled)
{
// do whatever here
}
});
}
Я не понимаю, чего должен достичь ваш
await Task.Delay(-1);
. Что будет, если просто удалить его?