taurus2790
@taurus2790
Я не программер я только учусъ

Как запустить Task на определённое время?

Всем добрый вечер.

Из за отсутствия опыта не могу решить задачку. Буду благодарен за помощь.

Есть класс и метод который через сокет получает название сервера Server.GetServerName();
Теперь когда сервер активен, данные получаются быстро и хорошо, без глюка. Но если сервер подтупливает или нагружен или вообще отключен, то приложение полностью повисает пака либо не придёт ответ либо сокет не отвалится.

Я понимаю, что нужно запустить через таску Task.Run(() => Server.GetServerName()); А так же асинхронно.

Но если так, то поток будет висеть пака не отвалится сокет, либо вообще бесконечно.

Подскажите можно как то используя Task-и и await/async сделать так, чтобы если Server.GetServerName() в течении 30 секунд не вернёт строку останавливаем и удаляем таску.

Хочу написать обёртку для Server.GetServerName() которая не будет вешать приложение, а так же будет возвращать пустую строку или кидать исключение если не смог получить данные. Но опыта и/или мозгов не хватает.
  • Вопрос задан
  • 195 просмотров
Решения вопроса 1
@basrach
string serverName = null;
	var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
	Task.Run(() => serverName = Server.GetServerName(), cancellationTokenSource.Token);


В таком случае вызов Server.GetServerName() будет происходить в фоне и не заблокирует основной поток. Теоретически через 30 секунд задача будет отменена. Но по факту задача будет висеть в режиме ожидание ответа по сети до тех пор, пока ответ не придет, и только после того как придет ответ будет выбран свободный поток из пула, который возьмет эту задачу для продолжения выполнения и возможно прервет её, но возможно что и не прервет.

Если вам гарантированно нужно чтобы задача не выполнилась после истечения 30 секунд, то нужно переделать метод GetServerName() следующим образом:
public string GetServerName(CancellationToken cancellationToken)
{
	// здесь непосредственно вызов по сети
	
	cancellationToken.ThrowIfCancellationRequested();
}

либо:
public string GetServerName(CancellationToken cancellationToken)
{
	// здесь непосредственно вызов по сети

	if (cancellationToken.IsCancellationRequested)
	{
		return;
	}
}

ну и соответственно его вызов будет выглядеть в таком случае вот так:
Server.GetServerName(cancellationTokenSource.Token)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@tex0
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы