秒表应用程序启动但不会停止

本文关键字:应用程序 启动 | 更新日期: 2023-09-27 17:56:16

由于某种原因,我能够启动秒表,但是当我尝试单击停止按钮时,没有任何反应。

我有一些Java编程的背景,但我被分配了一个项目,用一种我不懂的语言制作一个程序,所以我选择了C#。我对 C# 有一些了解,但如果有人可以帮助我解决这个问题,我将不胜感激。

using System;
using Gtk;
using System.Threading;
using System.Diagnostics;
using System.Timers;
public partial class MainWindow: Gtk.Window
{
    Stopwatch stopwatch = new Stopwatch();
    System.Timers.Timer timer  = new System.Timers.Timer();
    bool stopClicked = false;
    public MainWindow () : base (Gtk.WindowType.Toplevel)
    {
        Build ();
    }
    protected void OnDeleteEvent (object sender, DeleteEventArgs a)
    {
        Gtk.Application.Quit ();
        a.RetVal = true;
    }
    protected void OnStartButtonClicked (object sender, EventArgs e)
    {
        Thread thread1 = new Thread(new ThreadStart(Thread1));
        thread1.Start ();
        stopwatch.Start ();
        Console.WriteLine ("Stopwatch started");
        timer.Elapsed += new ElapsedEventHandler (timerTick);
        timer.Interval = 100;
        timer.Enabled = true;
        timer.Start ();
        Console.WriteLine ("Timer started");
    }
    protected void OnStopButtonClicked (object sender, EventArgs e)
    {
        stopClicked = true;
    }
    void timerTick(object sender, EventArgs e)
    {
        timeLabel.Text = stopwatch.Elapsed.ToString ();
        System.Windows.Forms.Application.DoEvents ();
    }
    void Thread1()
    {
        if(stopClicked)
        {
            timeLabel.Text = stopwatch.Elapsed.ToString ();
            timer.Stop ();
            timer.Enabled = false;
            timer.Dispose ();
            Console.WriteLine ("Timer stopped");
            stopwatch.Stop ();
            Console.WriteLine ("Stopwatch stopped");
        }
     }
 }

秒表应用程序启动但不会停止

您的线程没有执行任何操作。线程方法仅运行一次。您至少需要一个循环来检查stopClicked是否在某个时候被单击。

void Thread1()
{
    while (!stopClicked)
    {
        Thread.Sleep(100);
    }
    // Rest of the code to finish the timer.
}

实际上,我不太明白为什么您需要该线程。只需在单击停止按钮时停止计时器即可。这里不需要单独的线程。它会导致各种问题。

也没有必要做

System.Windows.Forms.Application.DoEvents();

无论如何,当计时器方法离开时,UI 将更新。这不是好的做法。此外,System.Timers.Timer是在单独的线程中调用的,因此您实际上应该在此处获得跨线程异常。

这是因为 Thread1 只运行一次,你应该使用繁忙的等待循环来做这件事,比如

void Thread1()
{
    while (true)
    {
        if (stopClicked)
        {
            timeLabel.Text = stopwatch.Elapsed.ToString();
            timer.Stop();
            timer.Enabled = false;
            timer.Dispose();
            Console.WriteLine("Timer stopped");
            stopwatch.Stop();
            Console.WriteLine("Stopwatch stopped");
            break;
        }
        Thread.Sleep(10);
    }
}

但是您可以将整个逻辑移动到OnStopButtonClicked,并且不再需要使用线程

protected void OnStopButtonClicked (object sender, EventArgs e)
{
    timeLabel.Text = stopwatch.Elapsed.ToString ();
    timer.Stop ();
    timer.Enabled = false;
    timer.Dispose ();
    Console.WriteLine ("Timer stopped");
    stopwatch.Stop ();
    Console.WriteLine ("Stopwatch stopped");
}

一个简单的解决方案是:

protected void OnStartButtonClicked (object sender, EventArgs e)
{
    stopwatch.Start ();
    // the next 3 lines could also be in the constructor function
    timer = new System.Timers.Timer();
    timer.Elapsed += new ElapsedEventHandler (timerTick);
    timer.Interval = 100;
    timer.Start ();
    Console.WriteLine ("Timer started");
}

protected void OnStopButtonClicked (object sender, EventArgs e)
{
    timer.Stop ();
    stopwatch.Stop ();
    Console.WriteLine ("Timer stopped"); 
}
void timerTick(object sender, EventArgs e)
{
    timeLabel.Text = stopwatch.Elapsed.ToString ();
}