C#

C#学习笔记 , 好记性不如烂笔头 (自己用的,请无视我)

串口号获取方法:


private void Form1_Load(object sender, EventArgs e)
{
string[] str;//定义一个字符型数组
str = System.IO.Ports.SerialPort.GetPortNames();//获取系统串口号数组
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
//分别添加到下拉菜单中
if (str.Length != 0)//若数组长度不为0
comboBox1.Text = str;//将数组第一个数据送给下拉框text显示
else comboBox1.Text = "";//否则空着
}
已邀请:

admin

赞同来自:

开启和关闭com口
uint16 com_open;
private void button1_Click(object sender, EventArgs e)
{
try
{
if (com_open == 1)
{
serialPort1.Close();
button1.Text = "开启";
com_open = 0;
return;
}
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.Open();
button1.Text = "关闭";
com_open = 1;
}
catch
{
if (com_open == 1)
MessageBox.Show("关闭失败!", "警告");
else
MessageBox.Show("开启失败", "警告");
}

}
如果发送的有中文字符,
则需要在打开串口之前设置字符集
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.Encoding = System.Text.Encoding.GetEncoding("gb2312");
serialPort1.Open();

以下再记录一个代码:转Unicode格式

public static string ToUnicode(string str)
{
byte[] data = Encoding.BigEndianUnicode.GetBytes(str);
int i = 0;
StringBuilder sb = new StringBuilder();
foreach (byte b in data)
{
if (i++ % 2 == 0) sb.Append("\\u");
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}

admin

赞同来自:

串口接收数据并发送到TEXTbox显示出来
这个里面有个问题,假如将下面的代码中的最后一句改成
textBox2.AppendText(str);
不使用delegate继承的话,会报错
:线程间操作无效: 从不是创建控件“textBox2”的线程访问它。
说明串口处理事件是在其他线程进行的,直接在串口事件里面直接调用TEXtbox显示
是不行的,TEXTbox用的事主线程,
可以取消线程间检查:
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
也可以将串口事件中的TEXTbox定义为继承即可.

如下:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string str;
str = serialPort1.ReadExisting();
BeginInvoke((EventHandler)delegate { textBox2.AppendText(str); });

}

注意:我把原来最后一句中的Invoke改成了BeginInvoke,前面一个是在拥有此控件的基础窗口句柄的线程上执行指定的委托。后面一个是:在创建控件的基础句柄所在线程上异步执行指定委托。
两者的区别去看下面额文章:
http://www.cnblogs.com/mashang ... .html

admin

赞同来自:

关于使用 backgroundWorker 控件问题:
官网说明地址:
https://msdn.microsoft.com/zh- ... .aspx
貌似可以代替Thread线程操作.
里面包含了三个Callback
backgroundWorker1_DoWork() //调用 RunWorkerAsync 时发生
backgroundWorker1_ProgressChanged() //调用 ReportProgress 时发生。
backgroundWorker1_RunWorkerCompleted() //当后台操作已完成、被取消或引发异常时发生

BackgroundWorker 类允许您在单独的专用线程上运行操作。 耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。 如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度并在操作完成时发出信号的事件。 可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。 如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
若要为后台操作做好准备,请添加 DoWork 事件的事件处理程序。 在此事件处理程序中调用耗时的操作。 若要开始此操作,请调用 RunWorkerAsync。 若要收到进度更新的通知,请处理 ProgressChanged 事件。 若要在操作完成时收到通知,请处理 RunWorkerCompleted 事件


根据官方第一个例子:
我自己添加了个ctime记录按键按下次数
private void startAsyncButton_Click(object sender, EventArgs e)
{
//ctime++;
if (backgroundWorker1.IsBusy != true)
{
ctime++;
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();//开启线程
}
label1.Text = ctime.ToString ();
}

可以看出,为了不在BW启动后运行过程中被再次开启导致出错,所以粗体部分很重要
这样就算你在开启后运行中再次点击按钮,开启操作是不会再次执行的,因为此时
backgroundWorker1.IsBusy = busy
看下面的:
private void cancelAsyncButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
// Cancel the asynchronous operation.
backgroundWorker1.CancelAsync();//取消线程
}
}
其实判断backgroundWorker1.WorkerSupportsCancellation == true这个完全没有必要,因为我们确实开启了,可以删掉..
继续看:

private void backgroundWorker1_DoWork/b
{
[b]BackgroundWorker worker = sender as BackgroundWorker;


for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
//这个应该就是sleep了吧?和VC有啥区别?线程延时休眠500ms???
//貌似是将当前线程休眠........就是这个BW线程?
//休眠的时间可以用于让其他线程完成当前工作,亦可以减少CPU占用时间
worker.ReportProgress(i * 10);
}
}
}
这个是DoWork的事件,注意后面的 e,后面会用到
这个线程的任务是产生一个过程量

admin

赞同来自: L

继续: 上面调用了worker.ReportProgress(i * 10);,这样每次调用就会进入进程事件函数
private void backgroundWorker1_ProgressChanged/b
{
resultLabel.Text = ([b]e.ProgressPercentage
.ToString() + "%");
}
注意到粗体部分,意思是获取异步任务的进度百分比,这个百分比来自上面的
worker.ReportProgress(i * 10);传递来的....
紧接着事件处理完成事件触发了
private void backgroundWorker1_RunWorkerCompleted/b
{
if (e.Cancelled == true)
{
resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
resultLabel.Text = "Done!";
}
}
完成函数尽量要这样写,要判断是自主取消还是错误导致,或者是事件完成了.
这里还有一个要重点知道的 resultLabel.Text = [b]e.Result
.ToString();
表示获取异步操作结果的值.....

admin

赞同来自: L

backgroundWorker的这个线程是可以传递参数的.
比如:开启函数可以这样
backgroundWorker1.RunWorkerAsync(test);//开启线程
但是其中test只能有一个,即参数只能是一个!
如果想传递多个参数,那么可以将test封装成结构体或者object,例如
先定义一个类:

    public class Testobj
{
public int onevalue { get; set; }
public int twovalue { get; set; }
}

然后全局初始化一下:

        Testobj test = new Testobj
{
onevalue = 5,
twovalue = 4
};

然后初始化开启BW的时候,用

if (backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync(test);
}
这样多个参数就传递过去了.
应用的时候这样用:


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Testobj str = e.Argument as Testobj; //重点
UInt16 i;

for (i = 1; i <= 10; i++)
{
if (worker .CancellationPending == true)//必须要有判断
{
e.Cancel = true;
break ;
}
System.Threading.Thread.Sleep(500);
if (i % 2 == 0)
worker.ReportProgress(str.onevalue);//ReportProgress这个最多传递两个参数
else
worker.ReportProgress(str.twovalue);

}
}

也可以这样用来传递两个参数到ReportProgress
worker.ReportProgress(str.onevalue,str.twovalue );
如果这样到时候获取就用
label1.Text = e.ProgressPercentage.ToString ()+e.UserState .ToString() ;
本来是:一个作为进度量,一个作为状态量的,现在都用来传递参数了.

最后: 完成事件里面用backgroundWorker1.Dispose();来释放资源

admin

赞同来自:

然而如果有好多个参数要返回:
比如 AD采集了8个通道的数据,那么应该怎么在采集完成后返回这些数据呢?
显然用ReportProgress不行,必须使用完成事件了,
完成事件同样可以将这个参数封装成一个结构体来用.
如下;
封装还是如楼上那样
public class Testobj
{
public int onevalue { get; set; }
public int twovalue { get; set; }
}
在Dowork声明,例如
Testobj ccstr = new Testobj { };//注意必须这样写
然后可以将采集的AD分别赋给这些变量,最后将这个变量提交给 e.Result 如:
ccstr.onevalue = 88;
ccstr.twovalue = 55;
e.Result = ccstr;
最后一个就是当BW完成后,调用完成事件,会自动将上面的参数传递

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Testobj ctest = e.Result as Testobj;//必须有这个
if (e.Error != null)
label1.Text = e.Error.Message;
else if (e.Cancelled == true)
label1.Text = "user cancel.";
else label1.Text = ctest.onevalue.ToString() + ctest.twovalue.ToString();
backgroundWorker1.Dispose();
}
ok,结果可以取出了.........

admin

赞同来自:

相似元件事件统一管理方法:
区别开是哪个元件产生的事件


private void CH_Checked(object sender, RoutedEventArgs e)
{
Control Ch_control = sender as Control;
// if (Ch_control.Name == "CH1")
// {
textbox_ch1.Text += Ch_control.Name.ToString();
// }

}

无语用分析

赞同来自: L

靠,C#,牛逼

admin

赞同来自: L

async 异步操作!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net.Http;
using System.Net;
using System.IO;
namespace WpfApplication2
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

}
**private void StartButton_Click(object sender, RoutedEventArgs e)
{
resultsTextBox.Clear();
CreateMultipleTasksAsync();
resultsTextBox.Text += "\r\n\r\nControl returned to startButton_Click.\r\n";
}**


private async Task CreateMultipleTasksAsync()
{
// Declare an HttpClient object, and increase the buffer size. The
// default buffer size is 65,536.
HttpClient client =
new HttpClient() { MaxResponseContentBufferSize = 1000000 };

// Create and start the tasks. As each task finishes, DisplayResults
// displays its length.
Task<int> download1 =
ProcessURLAsync("http://msdn.microsoft.com", client);
Task<int> download2 =
ProcessURLAsync("http://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client);
Task<int> download3 =
ProcessURLAsync("http://msdn.microsoft.com/en-u ... ot%3B, client);

// Await each task.
int length1 = await download1;
int length2 = await download2;
int length3 = await download3;

int total = length1 + length2 + length3;

// Display the total count for the downloaded websites.
resultsTextBox.Text +=
string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total);
}


async Task<int> ProcessURLAsync(string url, HttpClient client)
{
var byteArray = await client.GetByteArrayAsync(url);
DisplayResults(url, byteArray);
return byteArray.Length;
}


private void DisplayResults(string url, byte[] content)
{
// Display the length of each website. The string format
// is designed to be used with a monospaced font, such as
// Lucida Console or Global Monospace.
var bytes = content.Length;
// Strip off the "http://".
var displayURL = url.Replace("http://", "");
resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
}
}
}


上面的是先显示Control returned to startButton_Click.然后才慢慢逐条的显示采集到的数据长度

要回复问题请先登录注册