在WPF中从串行端口接收数据时执行某些操作

时间:2017-02-15 19:32:35

标签: c# wpf event-handling serial-port

我想创建程序,它会根据"实时"中的接收数据以任何方式为椭圆着色。数据类似于:x1-1x2-1等。

我有一个奇怪的问题,我可以在调试时看到,填充椭圆的颜色应该改变,但它不会发生。

我接收数据的部分代码:

 private void ReceiveData()
            {
                SerialPort serialPort = new SerialPort("COM1", 9600);
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                serialPort.Open();
            }

 private static void DataReceivedHandler(
                object sender,
                SerialDataReceivedEventArgs e)
            {
                SerialPort sp = (SerialPort)sender;
                string indata = sp.ReadExisting();
                if (indata.Contains(" "))
                {
                    testString = indata.Substring(0, 4);

                }
                Console.Write(indata);
            }

我可以在控制台中看到收到的数据,即使在点击按钮后开始接收数据。 testString是从x1-1中提取单indata,在接收数据期间仍在增长 private void button1_Click(object sender, RoutedEventArgs e) { ReceiveData(); while (true) { if (testString == "x1-1") x1.Fill = Brushes.Blue; else x1.Fill = Brushes.Red; } } 。我知道它不会像它应该的那样工作,但它现在并不重要。

按钮上的操作代码:

x1

heroku fork --from a***e-a*****e-94769 --to rd-test是椭圆形,我想要制作红色或蓝色。我可以在这个函数中设置断点,我可以看到它应该改变。我认为问题是,该程序正在等待关闭端口并完成传输,然后它可能会改变,但我需要在"实时"。谁知道怎么做?

2 个答案:

答案 0 :(得分:1)

我相信你会以错误的方式解决这个问题。您不必经常检查teststring的值,而只需启动通讯端口侦听器并让它在后台运行 - 因为这将是它自己的线程。然后,您需要创建一个数据绑定到颜色。每当comm端口侦听器解析一个字符串时,它就会自动更新颜色。

首先,在CommPort类中:

class MyCommPort : INotifyPropertyChanged
{
    SerialPort serialPort = null;
    public MyCommPort()
    {
        serialPort = new SerialPort("COM3", 9600);
        serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
        serialPort.Open();
    }
    ~MyCommPort()
    {
        serialPort.Close();
    }

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string testString = null;
        string indata = sp.ReadLine();
        if (indata.Length >= 4)
        {
            testString = indata.Substring(0, 4);
            // Update the value
            if (testString == "x1-1") EllipseBrush = Brushes.Blue;
            else EllipseBrush = Brushes.Red;
        }
        Console.Write(testString);
    }

    // Create a property that will be bound
    private SolidColorBrush ellipseBrush = Brushes.Red;
    public SolidColorBrush EllipseBrush
    {
        get { return ellipseBrush; }
        set
        {
            ellipseBrush = value;
            OnPropertyChanged("EllipseBrush");
        }
    }

    // Extend the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            // Alert anyone bound to this that the value has changed
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

然后,将Ellipse的DataContext设置为CommPort类,并将Ellipse的Fill属性绑定到EllipseBrush。 现在你所要做的就是启动Commport监听器(ReceiveData();),颜色更新应该自动发生。

例如:MainWindow.xaml

<Window x:Class="delete_me.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Ellipse x:Name="ellipse" Fill="{Binding Path=EllipseBrush}" />
    </Grid>
</Window>

后面的代码:MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ellipse.DataContext = new MyCommPort();
    }
}

答案 1 :(得分:0)

不要通过在按钮单击事件中包含while(true)来挂起UI线程。使用DispatchTimer来代替每500秒做一次工作。

System.Windows.Threading.DispatcherTimer MyTimer = null;
private void ReceiveData()
{
    MyTimer = new System.Windows.Threading.DispatcherTimer();
    MyTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
    MyTimer.Tick += MyTimer_Tick;
    MyTimer.Start();
    SerialPort serialPort = new SerialPort("COM1", 9600);
    serialPort.DataReceived += new 
             SerialDataReceivedEventHandler(DataReceivedHandler);
    serialPort.Open();
}

private static void DataReceivedHandler(
                object sender,
                SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    if (indata.Contains(" "))
    {
        testString = indata.Substring(0, 4);

    }
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    ReceiveData();
}

private void MyTimer_Tick(object sender, EventArgs e)
{
    if (testString == "x1-1")
    {
       x1.Fill = Brushes.Blue;
    }
    else 
    {
       x1.Fill = Brushes.Red;
    }
}