【问题标题】:C# simple stopwatch - Total beginnerC# 简单秒表 - 初学者
【发布时间】:2020-07-13 14:20:00
【问题描述】:

我来自嵌入式 C 编程,我对 oop、任务、线程、ecc 完全不了解。 我正在了解 C# 和 oop 的基本概念,并想尝试编写一个简单的秒表。

目标:用按钮切换秒表状态,并在按钮内部显示值。

到目前为止,我已经做到了:

namespace Cronometro
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }
    }

    public class MyTimerClass
    {
        private DateTime TimeValue;
        private System.Timers.Timer TimerObj;
        private const int TimeInterval = 1;

        public MyTimerClass()
        {
            TimeValue new DateTime(0, 0, 0, 0, 0, 0, 0, DateTimeKind.Local);
            TimerObj = new System.Timers.Timer(TimeInterval);
            TimerObj.AutoReset = true;

            TimerObj.Elapsed += TimerObj_Elapsed;
        }

        private void TimerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TimeValue = TimeValue.AddMilliseconds((double)TimeInterval);
        }

        public void Start()
        {
            TimerObj.Start();
        }
        public void Stop()
        {
            TimerObj.Stop();
        }
    }
}

说到这里,我只是想用 Button.Content 打印值,但似乎我不能在 MainWindow 类之外使用它。

我该怎么办?我开始考虑在主类中创建一个任务并等待计时器事件打印值,但我对线程和任务一无所知。

【问题讨论】:

  • 首先,在表单上添加一个按钮。没有按钮,您将无法按下它。
  • 为什么要包装Timer 类?您似乎没有在那里添加任何值,因此只需在没有包装器的主类中使用它并处理 elapsed 事件。
  • 我明白你的观点@RonBeyer,但这只是为了练习课程。

标签: c# system.timers.timer


【解决方案1】:

目前还不清楚您的意思,因为目前您根本无法在 MainWindow 类中使用它。只需通过公共函数公开值,您就可以在任何地方获取实例的值。

namespace Cronometro
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var x = new MyTimerClass();       // <<<
            x.Start();                        // <<<
            var timeValue = x.GetTimeValue(); // <<<
        }
    }

public class MyTimerClass
{
    private DateTime TimeValue;
    private System.Timers.Timer TimerObj;
    private const int TimeInterval = 1;

    public MyTimerClass()
    {
        TimeValue new DateTime(0, 0, 0, 0, 0, 0, 0, DateTimeKind.Local);
        TimerObj = new System.Timers.Timer(TimeInterval);
        TimerObj.AutoReset = true;

        TimerObj.Elapsed += TimerObj_Elapsed;
    }

    private void TimerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        TimeValue = TimeValue.AddMilliseconds((double)TimeInterval);
    }

    public DateTime GetTimeValue() // <<<
    {                              // <<<
        return TimeValue;          // <<<
    }                              // <<<

    public void Start()
    {
        TimerObj.Start();
    }
    public void Stop()
    {
        TimerObj.Stop();
    }
}

【讨论】:

  • 我发现了dispatcher的东西,好像是解决问题的办法?计时器和 UI 在不同的线程中运行,因此不仅仅是对象范围的问题。
【解决方案2】:

【讨论】:

  • 异步/等待秒表?做什么?这里没有异步操作
【解决方案3】:

填充按钮文本的一种方法是在MyTimerClass 类中创建一个事件,并从MainWindow 类内部将一个侦听器委托附加到它。

然后,在MyTimerClass 中触发TimerObj_Elapsed 中的事件,以便调用MainWindow 中的事件处理程序,您将有机会填充按钮。

但是,除了“练习课”之外,还有其他事情需要处理。因为您使用的是线程池计时器,所以计时器的Elapsed 事件处理程序是从工作线程调用的。在 GUI 应用程序中,只有主 / UI 线程可以与控件交互。所以很有可能,在尝试设置Button.Text 时会出现异常。您需要将 set 操作编组到 UI 线程。

坦率地说,如果您正在练习用 C# 编写课程,我建议您使用控制台应用程序而不是 GUI 应用程序开始。如果人们同时在桌面上抛出太多你不知道的概念,这可能不是一个好主意。

【讨论】:

  • 你说得对,就我目前的知识而言,这太复杂了。我认为这将是一个简单的第一个项目,但在这一点上很明显它不是
  • 你正在练习窗口类和后台计时器之间的通信,这不是一个开始的话题。如果你想使用定时器,从一个窗口类开始,使用winform定时器docs.microsoft.com/en-us/dotnet/api/…
  • 如果项目是 WPF,则为 DispatcherTimer
猜你喜欢
  • 2021-12-05
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多