做上位机,经常会有实时刷新日志内容的需求,比如接收串口消息、MQTT接收消息,常用的方法是Invoke函数 + TextBox.AppendText,比如- Invoke((new Action(() =>
- {
- String msg = "串口消息" + Environment.NewLine;
- txtReceiveMessage.AppendText(string.Format("{0} - {1}",DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"),msg));
- })));
复制代码 但是这种方式有两个弊端,一是日志长度靠TextBox.MaxLength属性控制,不能准确到行;二来消息只能逐个向后添加,不好调整顺序。
想要更灵活地刷新日志内容,可以使用AsyncOperation类与数据绑定功能。
AsyncOperation :C#中用来跟踪异步操作的生存期的类,其中的Post函数,可以从异步操作中向主进程发送消息。
数据绑定:C#中一种非常强大的功能,它允许开发者将控件属性与数据源连接起来,实现自动更新和同步。
默认情况下,绑定在TextBox、Label上的数据,只有在主进程上改动才能实时反应到界面上,跨线程操作会报错,这时则需要通过AsyncOperation类把“数据改动”这个消息发送到主界面上,才能正常展示,示例代码如下:
- public class AsyncProperty : INotifyPropertyChanged
- {
- protected AsyncOperation operation;
- public event PropertyChangedEventHandler PropertyChanged;
- public AsyncProperty()
- {
- operation = AsyncOperationManager.CreateOperation(null);
- }
- // 通过Post函数,将属性更改消息发送到主进程
- public void PostProperty(string propertyName)
- {
- operation.Post(new System.Threading.SendOrPostCallback(_ =>
- {
- if (PropertyChanged != null)
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }), null);
- }
- }
复制代码
- 继承AsyncProperty类,创建一个日志类LogContent
- public class LogContent : AsyncProperty
- {
- // 设置日志最大行数
- private int maxLine = 200;
- private int line = 0;
- private string _content = string.Empty;
- public string Content
- {
- get { return _content; }
- }
- public void InsertLog(string content)
- {
- line++;
- StringBuilder sb = new StringBuilder();
- sb.Append(content);
- sb.Append("\r\n");
- if (line > maxLine)
- {
- sb.Append(_content.Substring(0, indexOfNth(_content, maxLine, '\n', 1)));
- }
- else
- {
- sb.Append(_content);
- }
-
- _content = sb.ToString();
- PostProperty(nameof(Content));
- }
- public void ClearLog()
- {
- line = 0;
- _content = string.Empty;
- PostProperty(nameof(Content));
- }
- }
复制代码
- 把LogContent.Content绑定到TextBox.Text上即可
- public partial class Form1 : Form
- {
- LogContent logContent;
- public Form1()
- {
- InitializeComponent();
- logContent = new LogContent();
- textBox1.DataBindings.Add("Text", logContent, nameof(logContent.Content));
- }
- private void btnLog_Click(object sender, EventArgs e)
- {
- Thread thread = new Thread(WriteLog);
- thread.IsBackground = true;
- thread.Start();
- }
- private void WriteLog()
- {
- for (int i = 0; i < 500; i++)
- {
- Thread.Sleep(100);
- logContent.InsertLog(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
- }
- }
- }
复制代码 此时,跨线程调用的WriteLog函数,会将日志倒序实时刷新到界面上。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |