Используйте CancellationToken
как это:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
private string TotalTime;
static void Main(string[] args)
{
new Program().Run();
}
private void Run()
{
var cts = new CancellationTokenSource();
TotalTimer("00:00:00", cts.Token);
Console.ReadLine(); // waits for you to press 'Enter' to stop TotalTimer execution.
cts.Cancel();
Console.WriteLine("Press 'Enter' to exit the program.");
Console.ReadLine(); // waits for you to press 'Enter' to exit the program. See, TotalTimer stopped.
}
// your original method modified
async void TotalTimer(string time, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
TimeSpan timesp = DateTime.Now - DateTime.Parse(time);
TotalTime = timesp.Hours + " : " + timesp.Minutes + " : " + timesp.Seconds;
Console.WriteLine(TotalTime); // to see it's working
await Task.Delay(5000, token);
}
}
}
}
Обновление
@ Хенк Холтерман, согласно истории изменений if (string.IsNullOrEmpty(time))
выглядит как попытка разорвать петлю извне. Но это бессмысленно по двум причинам:
- строки неизменны
- если
time
является нулевым или пустым DateTime.Parse(time)
(это было в оригинальном посте) бросает перед проверкой
Добавление токена в Task.Delay
является хорошим моментом. Это экономит ресурсы, но не имеет значения для наблюдаемого поведения.
Update2
@ Аргон, код не зависит от wpf
, winforms
, console
или чего-либо еще. См. Минимальный wpf
пример ниже. Я проверил, что это работает. Если что-то не работает с вашим конкретным кодом, возможно, вы скрываете некоторые детали от нас.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string TotalTime;
private CancellationTokenSource cts;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
cts = new CancellationTokenSource();
TotalTimer("00:00:00", cts.Token);
}
async void TotalTimer(string time, CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
TimeSpan timesp = DateTime.Now - DateTime.Parse(time);
TotalTime = timesp.Hours + " : " + timesp.Minutes + " : " + timesp.Seconds;
label1.Content = TotalTime;
await Task.Delay(5000, token);
}
}
catch(OperationCanceledException)
{
label1.Content = "Canceled";
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}
}
}