winform 类似 webbrowser 显示控件_解决高频率刷新导致页面卡死使用用户控件和本地队列服务

9d6abf2ebd218632276d4f53c380d6c4.png

winform页面防止页面卡死的方法有很多。这里介绍一种本人实战过的,可以用于高频率刷新页面控件的方法。仅供参考。其中运用到的技术主要包括: 队列使用、线程使用、委托刷新、用户控件;

首先:封装本地队列服务

使用泛型,这样可以兼容多种数据类型刷新本地页面。主要代码如下:

/// /// 本地队列服务封装/// /// public class QueueServer{    public readonly object _lock = new object();    public readonly EventWaitHandle _wh = new AutoResetEvent(false);    public Queue 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();        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 queueServer = new QueueServer();    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;这样就能保证在两种情况下都可以正常使用,否则任然会导致界面卡死。

页面设计

f77d1244ee4e5c474608fcdd8b907632.png

页面设计比较简单,主要实现数据展现和右键清空。

最后页面调用:

经过上诉处理后,调用方法也比较简单:只需要将控件拖到指定的页面,然后使用控件的方法myRichTextBox1.RefreshRichText($" 第{info.Number}个,耗时{st.ElapsedMilliseconds} 毫秒");就可以疯狂的刷新页面,尤其在进行监控执行过程,显示处理日志流水时就可以很方便的使用。也便于在跟多的页面集成使用。当然使用队列的好处就是,保证执行顺序的先后关系,方便排查问题。不然高频率刷新,容易覆盖数据。

bbb997c75a9d065b8407534f67ba8035.png

好啦,如果对你有帮助的话,你也可以试试。有其他更有意思的处理方法,也可以留言互相交流。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值