Я хочу иметь метод, который запускает некоторую обработку, которая длится не более секунды, спит 5 минут и повторяется. Я также хочу, чтобы пользователь мог выйти из сна и уйти изящно. Я хочу, чтобы это работало в течение дня, не потребляя слишком много системных ресурсов. Каков лучший шаблон дизайна для этого?
Вот моя первая попытка:
- Я использую поток, чтобы ждать и делать обработку. Я не уверен, должен ли я использовать поток, поток пула потоков или задачу. Я не думаю, что это должно быть задачей, потому что нет никаких асинхронных операций ввода-вывода. Я также не думаю, что мне следует использовать таймер, потому что я хочу иметь возможность аккуратно остановить поток, не дожидаясь следующего интервала.
- Я использую AutoResetEvents для сигнализации между двумя потоками. Это позволяет внутреннему коду запускаться либо когда время истекло, либо когда пользователь хочет выйти.
- Я прошу прощения, если этот вопрос является дубликатом. Если так, я не могу найти это.
Вот мой код:
var areCanContinue = new AutoResetEvent(false);
bool shouldContinue = true;
var thread = new Thread(obj =>
{
while (true)
{
areCanContinue.WaitOne(TimeSpan.FromMinutes(5));
if (shouldContinue)
{
Process();
}
else
{
break;
}
}
});
thread.Start();
string response;
do
{
Console.WriteLine("Press 'q' to quit");
response = Console.ReadLine();
} while (response != "q");
shouldContinue = false;
areCanContinue.Set();
2 ответа
Задачи не обязательно для операций ввода-вывода. Фактически, это хороший вариант использования Task.Delay
(который внутренне оборачивает таймер):
public static async Task ProcessAsync(CancellationToken cancellationToken)
{
try
{
while (true)
{
await Task.Delay(TimeSpan.FromMinutes(5), cancellationToken).ConfigureAwait(false);
Process();
}
}
catch (TaskCanceledException)
{
// Cancellation requested, do whatever cleanup you need then exit gracefully
}
}
Тогда использовать это:
var cancellationTokenSource = new CancellationTokenSource();
var task = ProcessAsync(cancellationTokenSource.Token);
string response;
do
{
Console.WriteLine("Press 'q' to quit");
response = Console.ReadLine();
} while (response != "q");
cancellationTokenSource.Cancel();
task.Wait(); // Wait for the task to finish
В зависимости от ваших требований вы также можете напрямую использовать таймер:
var timer = new Timer(_ => Process(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
string response;
do
{
Console.WriteLine("Press 'q' to quit");
response = Console.ReadLine();
} while (response != "q");
timer.Dispose(); // Stop the timer
Надеюсь это поможет.
class Program
{
static void Main(string[] args)
{
Operation op = new Operation();
var tokenSource = new CancellationTokenSource();
Task.Factory.StartNew( async () => await op.LongRunningApplication(tokenSource.Token));
while(true)
{
Console.WriteLine("PRINT STOP for Cancellation...");
var str = Console.ReadLine();
if(string.Compare(str, "Stop", true) == 0)
{
Console.WriteLine("Cancellation Requested...");
tokenSource.Cancel();
Task.Delay(TimeSpan.FromSeconds(30)).Wait(); // Making Sure that It stops gracefully since this is console app
break;
}
}
Console.WriteLine("Completed");
}
}
public class Operation
{
public async Task LongRunningApplication(CancellationToken token)
{
Console.WriteLine("Starting long Running application....");
while (true)
{
await Task.Delay(1000); // Your Operation
Console.WriteLine("Wating...");
for (int i = 0; i < 30; i++)
{
await Task.Delay(TimeSpan.FromSeconds(10)); // Wait For 5 Mins (10 sec , 30 intervals)
if (token != null && token.IsCancellationRequested)
{
Console.WriteLine("Stopping GraceFully..");
return;
}
}
}
}
}
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.