我有一个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>
答案 0 :(得分:3)
这里的基本问题是,在用户取消消息框之前,您不会从计时器的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)));
}
}
这会将您的方法调用包装在一个委托中,该委托又被排队以便稍后在同一个线程(Dispatcher线程)中执行。这允许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
局部变量,以及在{1}}中设置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服务器自动调整时钟的唯一方法是改善显示的时间,如果当你的程序中的计数器启动时,系统时钟已经从正确的时间漂移得更远......这不是一个非常常见的情况。)