C# 简单秒表 - 初学者
Posted
技术标签:
【中文标题】C# 简单秒表 - 初学者【英文标题】:C# simple stopwatch - Total beginner 【发布时间】: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,但这只是为了练习课程。
【参考方案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】:首先,您不必编写自己的 Stopwatch 类。 DotNet 有自己的: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.8
其次,尝试理解 async/await 模式: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
所以,你可以这样做: https://wouterdekort.com/2013/10/01/async-and-await-and-the-ui-thread/
【讨论】:
异步/等待秒表?做什么?这里没有异步操作【参考方案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以上是关于C# 简单秒表 - 初学者的主要内容,如果未能解决你的问题,请参考以下文章