首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将数据发送到串口时的异步数字时钟

将数据发送到串口时的异步数字时钟
EN

Stack Overflow用户
提问于 2015-05-20 03:21:06
回答 1查看 441关注 0票数 3

我有一个WPF应用程序和一个用动态开发平台制作的数字时钟。WPF发送一个初始时间和5个警报。但是,当digital发出警报已被激活的通知时,WPF应用程序将其读取并显示为消息框,但当消息框被激活时,应用程序中的数字时钟会停止。我怎样才能保持时钟正常运转呢?

政务司司长

代码语言:javascript
复制
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

代码语言:javascript
复制
![<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>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-20 04:45:03

这里的基本问题是,在用户拒绝消息框之前,您不会从计时器的Tick事件处理程序返回。计时器在处理完当前事件之前不会发出另一个Tick事件。

与其在事件处理程序本身中显示消息框,不如使用Dispatcher.BeginInvoke()方法异步显示消息框:

代码语言:javascript
复制
    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事件处理程序返回,以便计时器能够继续运行。

也就是说,您的代码不太正确。IMHO,最明显,最重要的问题是,定时器(所有这些)并不是非常不准确。它们可以(正如您所看到的)由于各种原因而延迟,并且没有非常精确地计划执行。随着时间的推移,你的时钟很可能会偏离你想要显示的实际时间。

相反,您应该使用例如Stopwatch实例,当您希望时钟启动时启动它,将它的Elapsed值添加到您的初始值(即new TimeSpan(0, intHoras, intMinutos + 2),您可以计算它一次,并为此目的存储在类字段中),并使用适当的显式格式字符串(例如"hh:mm:ss tt")显示该和。

编辑:

这确实是次要的问题,但因为你问了…

跟踪时钟时间的更好方法如下:

1.在您的类中添加两个新字段:

代码语言:javascript
复制
private TimeSpan baseTime;
private Stopwatch elapsed;

2.启动计时器时初始化这些字段:

代码语言:javascript
复制
baseTime = new TimeSpan(0, intHoras, intMinutos + 2);
elapsed = Stopwatch.StartNew();

3.然后使用这些值在计时器的Tick事件处理程序中显示时间:

代码语言:javascript
复制
lblTime.Content = (baseTime + elapsed.Elapsed).ToString(@"hh\:mm\:ss");

自然,您将删除与时间显示相关的其他代码:初始化代码中的DateTimeTimeSpan局部变量,以及在Tick事件处理程序方法中设置lblTime.Content的现有语句。

最后,如果这会平息汉斯对Stopwatch的反对,您可以只使用DateTime来实现上面的内容。也就是说,不是上面提到的,而是做这样的事情:

1.在您的类中添加两个新字段:

代码语言:javascript
复制
private TimeSpan baseTime;
private DateTime startTime;

2.启动计时器时初始化这些字段:

代码语言:javascript
复制
baseTime = new TimeSpan(0, intHoras, intMinutos + 2);
startTime = DateTime.UtcNow;

3.然后使用这些值在计时器的Tick事件处理程序中显示时间:

代码语言:javascript
复制
lblTime.Content = (baseTime + (DateTime.UtcNow - startTime)).ToString(@"hh\:mm\:ss");

注意,UtcNow依赖于系统时钟,所以如果它改变了,这将影响显示的运行时间,导致它不正确。例如,如果用户更改了设定的时间,或者系统从NTP服务器自动更新时钟(从NTP服务器自动调整时钟的唯一方法是,如果系统时钟比程序中的计数器启动…时的正确时间偏移得更远,则会提高显示时间。这不是一个很常见的情况)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30339717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档