C#学习--项目实战之串口通信工具二
写在前面
上一篇文章讲解了串口通信的基本实现,这张讲一下我在做这个基于串口通信项目时遇到的问题,因为是一个比较针对性的项目,所以这篇文章可能不适合大多数人。
关于多线程处理接受数据
串口通信在实际的应用当中,常常会遇到这样的情况,接受到的数据接受并处理,然后在UI上做相应的显示,这个时候上位机程序运行的时间会大大影响串口通信的速度,所以这里要用多线程,接受工作线程接受到数据之后只做存储,后续操作交给其他工作线程来完成。上代码
public void StartSaveDataBW()
{
try
{
timeNow = DateTime.Now;
saveDatas_BW = new BackgroundWorker();
saveDatas_BW.DoWork += SaveDatas_BW_DoWork;
saveDatas_BW.ProgressChanged += SaveDatas_BW_ProgressChanged;
saveDatas_BW.WorkerReportsProgress = true;
saveDatas_BW.RunWorkerAsync();
}
catch (Exception)
{
MessageBox.Show("多线程启动失败");
}
}
private void SaveDatas_BW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == -10)
{
NotificationMessage msg = new NotificationMessage(this, Notifications.UpdateSaveProgress);
Messenger.Default.Send<NotificationMessage>(msg);
}
else if (e.ProgressPercentage == -1)
{
MessageBox.Show("数据保存失败");
}
}
private void SaveDatas_BW_DoWork(object sender, DoWorkEventArgs e)
{
while (IsStartSaveDataModel)
{
try
{
operation()//处理操作
saveDatas_BW.ReportProgress(-10);
}
catch (Exception ex)
{
ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
log.Info(ex.Message);
saveDatas_BW.ReportProgress(-1);
}
}
}
这里省略了接收数据的代码,接受数据代码可以参考上一篇文章,主要功能是接受并存储。
关于多线程更新UI
很多同学会说,我不想用多线程,我想直接访问主线程变动UI层,但会报错,这可怎么办啊。这里谈我的一些理解啊,注册路由事件其实就是创建一个隐藏的工作线程,满足触发条件就会开启这个线程,其实在你不经意之间已经熟练掌握多线程了,神不神奇!意不意外!那么的你的问题就找到原因了,因为接受数据也是注册的路由世界,所以你在接收数据里的操作都是在工作线程中完成的,你想要从工作线程直接访问主线程,就必须用到Dispatcher了,上代码
private void Receive(NotificationMessage msg)
{
if (msg.Notification == Notifications.UpdateTextBoxMessage && msg.Sender == mainViewModel)
{
System.Threading.Thread.Sleep(100);
this.Dispatcher.Invoke(new System.Action(() => {
test();//变动UI
}));
}
}
其实原理我也不太懂,意思就是,这部分代码帮你从工作线程切换回了主线程,这样更新UI就不成问题了。
关于接收数据的储存和处理
对于储存数据每个人应该都有自己的习惯和心得把,这里说一些我的心得和理解。
对于类似串口通信的情况,我会用队列来储存数据 “(Queue< T >)”,首先它是一个FIFO的集合,先进先出,便于数据的读取和维护,其次它的性能在Add和Remove上都是O(1) (这个同学们可以百度关键词“集合性能”),这里知道队列的Add和Remove操作都非常快就行了。这两个主要原因让我选择用队列来做为存储数据的一个集合。
public Queue<List<double>[]> saveAnalogChannelsDataQ = new Queue<List<double>[]>();
saveAnalogChannelsDataQ.Enqueue(Item1);
Item2 = saveAnalogChannelsDataQ.Dequeue();
关于数据的处理本文不做过多的讲解,下一篇文章里将会详细讲解:我理解的数据储存原理。
写在结尾
结尾给大家说个经历吧,之前有一篇文章我说过,培训班挺好的,现在我收回这句话,培训班也是因人而异的,我前几天就碰到这么一个朋友(贴吧认识的),他发了一个问题贴,我就评论了两句,然后他就加了我好友,问了我几个问题,但我没有立刻回答他(拒绝伸手党)。我跟他聊了几句,他是看培训视频学的,看完一部分,视频里的老师运行成功了,然后他跟着把代码打出来,但是呢,他却运行不成功,本着授人以鱼不如授人以渔的心态,我说:朋友,你要真想学就放下视频,买基础的书先看看,了解一下这个语言。我以为他会欣然接受,转折来了,他来了一句,书上的东西太基础了。。。。所以我觉得现在是个阿猫阿狗都拍个教学视频给别人看,真的误认子弟,一步一步的打代码,但凡有手会26个字母的,谁做不出来?这就给了很多新人一个错觉,看着自己写的代码洋洋得意,编程也就这样嘛,我这不就完成了么,其实呢,但凡里面错一个大小写,他都不知道问题出在哪里,VS工具也不会用,报错也不会看,所以我在这里再次声明,我的文章不适合新手看,我只是谈论一些自己的理解,如果有同学觉得我说的有问题,欢迎来讨论。