我有一个WPF应用程序和一个用Kinetis开发平台制作的数字时钟。 WPF发送初始时间和5条警报。但是,当Kinetis发送有关警报已激活的通知时,WPF应用程序会读取警报并显示为消息框,但在激活消息框时,应用程序中的数字时钟会停止。如何保持时钟运转?
CS
public partial class MainWindow : Window
{
SerialPort sp;
public MainWindow()
{
InitializeComponent();
}
void timer_Tick(object sender, EventArgs e)
{
lblTime.Content = Convert.ToDateTime(lblTime.Content).AddSeconds(1).ToLongTimeString();
int btr = sp.BytesToRead;
if (btr != 0)
{
string alarma = char.ConvertFromUtf32(sp.ReadChar());
MessageBoxResult result = MessageBox.Show("La alarma " + alarma + " se activo", "Alarma", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int intHoras = Convert.ToInt32(Horas.Text == "" ? "-1" : Horas.Text);
int intMinutos = Convert.ToInt32(Minutos.Text == "" ? "-1" : Minutos.Text);
int intHoras1 = Convert.ToInt32(Horas1.Text == "" ? "-1" : Horas1.Text);
int intMinutos1 = Convert.ToInt32(Minutos1.Text == "" ? "-1" : Minutos1.Text);
int intHoras2 = Convert.ToInt32(Horas2.Text == "" ? "-1" : Horas2.Text);
int intMinutos2 = Convert.ToInt32(Minutos2.Text == "" ? "-1" : Minutos2.Text);
int intHoras3 = Convert.ToInt32(Horas3.Text == "" ? "-1" : Horas3.Text);
int intMinutos3 = Convert.ToInt32(Minutos3.Text == "" ? "-1" : Minutos3.Text);
int intHoras4 = Convert.ToInt32(Horas4.Text == "" ? "-1" : Horas4.Text);
int intMinutos4 = Convert.ToInt32(Minutos4.Text == "" ? "-1" : Minutos4.Text);
int intHoras5 = Convert.ToInt32(Horas5.Text == "" ? "-1" : Horas5.Text);
int intMinutos5 = Convert.ToInt32(Minutos5.Text == "" ? "-1" : Minutos5.Text);
if ((intHoras <= 24) && (intMinutos <= 60) && (intHoras >= 0) && (intMinutos >= 0) &&
(intHoras1 <= 24) && (intMinutos1 <= 60) && (intHoras1 >= 0) && (intMinutos1 >= 0) &&
(intHoras2 <= 24) && (intMinutos2 <= 60) && (intHoras2 >= 0) && (intMinutos2 >= 0) &&
(intHoras3 <= 24) && (intMinutos3 <= 60) && (intHoras3 >= 0) && (intMinutos3 >= 0) &&
(intHoras4 <= 24) && (intMinutos4 <= 60) && (intHoras4 >= 0) && (intMinutos4 >= 0) &&
(intHoras5 <= 24) && (intMinutos5 <= 60) && (intHoras5 >= 0) && (intMinutos5 >= 0))
{
sp = new SerialPort("COM3");
sp.BaudRate = 19200;
sp.Open();
WriteTime(sp, intHoras, intMinutos);
WriteTime(sp, intHoras1, intMinutos1);
WriteTime(sp, intHoras2, intMinutos2);
WriteTime(sp, intHoras3, intMinutos3);
WriteTime(sp, intHoras4, intMinutos4);
WriteTime(sp, intHoras5, intMinutos5);
DateTime date = new DateTime();
TimeSpan ts = new TimeSpan(0, intHoras, intMinutos + 2);
date = date + ts;
lblTime.Content = date.ToLongTimeString();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
else
{
MessageBoxResult result = MessageBox.Show("Ingresaste datos incorrectos", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void WriteTime(SerialPort sp, int intHoras, int intMinutos)
{
List<byte[]> horas = getVectorNumber(intHoras);
List<byte[]> minutos = getVectorNumber(intMinutos);
foreach (byte[] item in horas)
{
sp.Write(item, 0, 1);
}
foreach (byte[] item in minutos)
{
sp.Write(item, 0, 1);
}
}
private List<byte[]> getVectorNumber(int number)
{
List<byte[]> result = new List<byte[]>();
result.Add(Encoding.ASCII.GetBytes(Convert.ToString(number / 10)));
result.Add(Encoding.ASCII.GetBytes(Convert.ToString(number % 10)));
return result;
}
#region NumericValidation
private void textBoxValue_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !TextBoxTextAllowed(e.Text);
}
private void textBoxValue_Pasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
String Text1 = (String)e.DataObject.GetData(typeof(String));
if (!TextBoxTextAllowed(Text1)) e.CancelCommand();
}
else e.CancelCommand();
}
#endregion
private Boolean TextBoxTextAllowed(String Text2)
{
return Array.TrueForAll<Char>(Text2.ToCharArray(),
delegate(Char c) { return Char.IsDigit(c) || Char.IsControl(c); });
}
}
XAML
![<Window x:Class="DigitalPITClock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="579.254" Width="877.835">
<Grid Background="Gray" Margin="0,0,-4.8,-55">
<Label Name="lblTime" FontSize="48" HorizontalAlignment="Left" Margin="297,22,0,0" VerticalAlignment="Top" Height="83" Width="269" RenderTransformOrigin="0.495,0.468"/>
<Label Content="Ingrese las horas y los minutos" HorizontalAlignment="Left" Margin="324,105,0,0" VerticalAlignment="Top" FontSize="15px"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="270,157,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox Name="Horas" HorizontalAlignment="Left" Margin="363,157,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="445,157,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox Name="Minutos" HorizontalAlignment="Left" Margin="544,157,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Alarma 1" HorizontalAlignment="Left" Margin="171,207,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.487,0.445"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="25,253,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox x:Name="Horas1" HorizontalAlignment="Left" Margin="118,253,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="200,253,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox x:Name="Minutos1" HorizontalAlignment="Left" Margin="299,253,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Alarma 2" HorizontalAlignment="Left" Margin="170,324,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.487,0.445"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="24,363,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox x:Name="Horas2" HorizontalAlignment="Left" Margin="117,363,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="199,363,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox x:Name="Minutos2" HorizontalAlignment="Left" Margin="298,363,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Alarma 3" HorizontalAlignment="Left" Margin="385,421,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.487,0.445"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="249,473,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox x:Name="Horas3" HorizontalAlignment="Left" Margin="342,473,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="424,473,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox x:Name="Minutos3" HorizontalAlignment="Left" Margin="523,473,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Alarma 4" HorizontalAlignment="Left" Margin="614,207,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.487,0.445"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="476,258,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox x:Name="Horas4" HorizontalAlignment="Left" Margin="569,258,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="651,258,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox x:Name="Minutos4" HorizontalAlignment="Left" Margin="750,258,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Alarma 5" HorizontalAlignment="Left" Margin="614,324,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.487,0.445"/>
<Label Content="Horas" HorizontalAlignment="Left" Margin="477,363,0,0" VerticalAlignment="Top" Height="44" Width="59" FontSize="15px"/>
<TextBox x:Name="Horas5" HorizontalAlignment="Left" Margin="570,363,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="37" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Label Content="Minutos" HorizontalAlignment="Left" Margin="652,363,0,0" VerticalAlignment="Top" Height="29" Width="71" FontSize="15px"/>
<TextBox x:Name="Minutos5" HorizontalAlignment="Left" Margin="751,363,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="-0.906,0.034" Height="29" Width="38" PreviewTextInput="textBoxValue_PreviewTextInput" DataObject.Pasting="textBoxValue_Pasting" MaxLength="2" FontSize="15px"/>
<Button Content="Aplicar Cambios" HorizontalAlignment="Left" Margin="351,552,0,0" VerticalAlignment="Top" Width="113" Height="28" Click="Button_Click"/>
</Grid>
</Window>
最佳答案
这里的基本问题是,直到用户关闭了消息框,您才从计时器的Tick
事件处理程序中返回。在您处理完当前事件之前,计时器不会发出另一个Tick
事件。
您应该使用Dispatcher.BeginInvoke()
方法异步显示消息框,而不是在事件处理程序本身中显示消息框:
void timer_Tick(object sender, EventArgs e)
{
lblTime.Content = Convert.ToDateTime(lblTime.Content).AddSeconds(1).ToLongTimeString();
int btr = sp.BytesToRead;
if (btr != 0)
{
string alarma = char.ConvertFromUtf32(sp.ReadChar());
Dispatcher.BeginInvoke((Action)(() =>
MessageBox.Show("La alarma " + alarma + " se activo", "Alarma",
MessageBoxButton.OK, MessageBoxImage.Exclamation)));
}
}
这会将您的方法调用包装在一个委托中,该委托又被排队,以便稍后在同一线程(分派器线程)中执行。这允许
Tick
事件处理程序返回,以便计时器可以继续运行。也就是说,您的代码不太正确。恕我直言,要解决的最明显,最重要的问题是计时器(所有计时器)不是很准确。如您所见,它们可能由于各种原因而被延迟,并且没有计划好精确地执行它们。随着时间的流逝,您的时钟很可能会与您要显示的实际时间发生偏差。
相反,您应该使用例如
Stopwatch
的实例,在您希望时钟启动时将其启动,将其Elapsed
值添加到初始值(即new TimeSpan(0, intHoras, intMinutos + 2)
,您可以计算一次并为此存储在类字段中),并且用适当的显式格式字符串(例如"hh:mm:ss tt"
)显示该总和。编辑:
这确实是原始问题的第二要因,但是既然您问过……
更好地跟踪时钟时间的方法如下:
1.向您的班级添加两个新字段:
private TimeSpan baseTime;
private Stopwatch elapsed;
2.启动计时器时初始化以下字段:
baseTime = new TimeSpan(0, intHoras, intMinutos + 2);
elapsed = Stopwatch.StartNew();
3.然后使用这些值在计时器的
Tick
事件处理程序中显示时间:lblTime.Content = (baseTime + elapsed.Elapsed).ToString(@"hh\:mm\:ss");
自然,您将删除其他与时间显示相关的代码:初始化代码中的
DateTime
和TimeSpan
局部变量,以及在lblTime.Content
事件处理程序方法中设置Tick
的现有语句。最后,如果它能平息汉斯对
Stopwatch
的反对,则可以仅使用DateTime
来实现上述内容。也就是说,代替以上内容,执行以下操作:1.向您的班级添加两个新字段:
private TimeSpan baseTime;
private DateTime startTime;
2.启动计时器时初始化以下字段:
baseTime = new TimeSpan(0, intHoras, intMinutos + 2);
startTime = DateTime.UtcNow;
3.然后使用这些值在计时器的
Tick
事件处理程序中显示时间:lblTime.Content = (baseTime + (DateTime.UtcNow - startTime)).ToString(@"hh\:mm\:ss");
请注意,
UtcNow
依赖于系统时钟,因此,如果更改它,将影响显示的经过时间,从而导致它不正确。例如,如果用户更改了设置时间,或者系统自动更新了NTP服务器的时钟(自动调整NTP服务器的时钟会改善显示时间的唯一方法是,如果系统时钟偏离时钟正确的时间,而不是启动程序中的计数器时已经漂移的时间……这不是很常见的情况)。关于c# - 将数据发送到串行端口时的异步数字时钟,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30339717/