前言:
今天兄弟们对“执行刷新操作时线程出现异常”大致比较着重,姐妹们都需要分析一些“执行刷新操作时线程出现异常”的相关内容。那么小编也在网络上汇集了一些关于“执行刷新操作时线程出现异常””的相关文章,希望看官们能喜欢,大家快快来了解一下吧!winform页面防止页面卡死的方法有很多。这里介绍一种本人实战过的,可以用于高频率刷新页面控件的方法。仅供参考。其中运用到的技术主要包括: 队列使用、线程使用、委托刷新、用户控件;
首先:封装本地队列服务
使用泛型<T>,这样可以兼容多种数据类型刷新本地页面。主要代码如下:
/// <summary>/// 本地队列服务封装/// </summary>/// <typeparam name="T"></typeparam>public class QueueServer<T>{ public readonly object _lock = new object(); public readonly EventWaitHandle _wh = new AutoResetEvent(false); public Queue<T> Queue; private readonly Thread th; //处理事件 public delegate void EventHandlerProcessing(T item); public EventHandlerProcessing Processing; //刷新队列剩余数量 public delegate void EnentHandlerRefresh(int Count); public EnentHandlerRefresh Refreshing; public QueueServer() { Queue = new Queue<T>(); th = new Thread(Work) { IsBackground = true }; } public void Start() { th.Start(); } public void Stop() { if (th != null && th.ThreadState != ThreadState.Stopped) { th.Abort(); } } public QueueServer(EventHandlerProcessing Processing) { this.Processing += Processing; th = new Thread(Work) { IsBackground = true }; } private void Work() { while (true) { T item = default(T); lock (_lock) { if (Queue.Count > 0) { item = Queue.Dequeue(); Refreshing?.Invoke(Queue.Count); if (item == null) { return; } } } if (item != null) { Processing?.Invoke(item); } else { _wh.WaitOne(); } } } public void Enqueue(T item) { lock (_lock) { if (!Queue.Contains(item)) { Queue.Enqueue(item); } } _wh.Set(); }}
然后 新增用户控件MyRichTextBox;
主要代码如下,其中引用队列服务。在引用的组件中启动队列线程,注册刷新事件 Refresh到队列服务刷新事件。对外提供刷新方法RefreshRichText(string text),将需要刷新的文本加入队列。编译好后可以在工具栏中直接使用
[ToolboxItem(true)]public partial class MyRichTextBox : UserControl{ private readonly QueueServer<string> queueServer = new QueueServer<string>(); public override string Text { get { return richTextBox1.Text; } set { richTextBox1.Text = value; } } public MyRichTextBox() { InitializeComponent(); queueServer.Processing += Refresh; queueServer.Start(); } private void richTextBox1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { contextMenuStrip1.Show(richTextBox1, new Point(e.X, e.Y)); } } private void toolStripMenuItem1_Click(object sender, EventArgs e) { richTextBox1.Clear(); } public void AppendText(string msg) { richTextBox1.AppendText(msg); richTextBox1.SelectionStart = richTextBox1.Text.Length; richTextBox1.ScrollToCaret(); } private void Refresh(string msg) { if (InvokeRequired) { Invoke(new Action(() => { if (Text.Length > 2000) { Text = ""; } AppendText($"{DateTime.Now.ToString("MM-dd HH:mm:ss ffff")} {msg} {Environment.NewLine}"); })); } else { if (Text.Length > 2000) { Text = ""; } AppendText($"{DateTime.Now.ToString("MM-dd HH:mm:ss ffff")} {msg} {Environment.NewLine}"); } } public void RefreshRichText(string msg) { queueServer.Enqueue(msg); }}
其中有一个地方要注意的是
Refresh方法中,当出现主线程访问InvokeRequired = false;执行下面的这种刷新方法,当控件被使用在子线程中时,InvokeRequired = true;这样就能保证在两种情况下都可以正常使用,否则任然会导致界面卡死。
页面设计
页面设计比较简单,主要实现数据展现和右键清空。
最后页面调用:
经过上诉处理后,调用方法也比较简单:只需要将控件拖到指定的页面,然后使用控件的方法myRichTextBox1.RefreshRichText($" 第{info.Number}个,耗时{st.ElapsedMilliseconds} 毫秒");就可以疯狂的刷新页面,尤其在进行监控执行过程,显示处理日志流水时就可以很方便的使用。也便于在跟多的页面集成使用。当然使用队列的好处就是,保证执行顺序的先后关系,方便排查问题。不然高频率刷新,容易覆盖数据。
好啦,如果对你有帮助的话,你也可以试试。有其他更有意思的处理方法,也可以留言互相交流。
标签: #执行刷新操作时线程出现异常