• C#跨线程操作控件


    在看别人代码的时候总是会Invoke和BeginInvoke方法,虽然大致明白是什么意思,但却不能很好的使用,上网查了很多资料,刚巧看到自己求学期间转载过一篇博文:

    c#Invoke和BeginInvoke的区别

     博文中讲的都是一些理论知识,本文介绍几个常见的问题:

     .net平台下Winform、wpf禁止跨线程直接访问控件,因此在必须跨线程访问控件的时候采用异步方式。

    1、winform项目中跨线程访问控件:

      编写一个Winform小实例:在做winform项目中,有时为了将系统运行的状态实时显示到Form中,因此添加一个RichTextbox控件实时显示系统运行日志。本例实现的操作是将日志以字符串的形式写入RichTextbox控件,因为是实时显示,所以涉及到跨线程输入的问题。

        private delegate void setRichTexBox(string s);
            public void setText(string txt)
            {
                if (this.t_revmsg.InvokeRequired)//等待异步
                {
                    setRichTexBox fc = new setRichTexBox(Set);
                    this.Invoke(fc, new object []{ txt});
                }
                else
                {
                    this.t_revmsg.AppendText(txt);
                }
            }
    private void Set(string txt) { t_revmsg.AppendText(txt); }

    控件的InvokeRequired的值为true时,说明有一个不属于创建它的线程要访问它,此时需要采用异步的方式进行操作。

    可以改进:

    private delegate void setRichTexBox(string s);
    
            public void SetText(string txt)
            {
                if (this.tbReceiveMsg.InvokeRequired)//等待异步
                {
                    setRichTexBox fc = new setRichTexBox(SetText);
                    this.Invoke(fc, new object[] { txt });
                }
                else
                {
                    this.tbReceiveMsg.AppendText(txt);
                }
            }

    2、wpf项目中跨线程访问控件:

      wpf的page页中,加入一个button控件和textbox控件,点击button实现添加textbox控件中的内容。

    private void button2_Click(object sender, RoutedEventArgs e)
            {
                this.textBox1.Dispatcher.Invoke(new WriteDelegate(WriteMethod), "asdf");
            }
    
            private delegate void WriteDelegate(string str);
            private void WriteMethod(string str)
            {
                this.textBox1.AppendText(str);
    
            }

    3、wpf项目中跨线程获取textbox控件中的内容

      本实例实现的功能是:点击button控件,开启socket监听服务。监听的端口需要从UI界面中的textbox中获取,因为不是创建它的线程访问它,因此才有Dispatcher.Invoke异步操作。稍作补充:在开启监听的过程中,有while(true)死循环,将其直接放入到主线程都会导致线程无法正常进行下去,解决方法是开启一个新的线程来开启监听。

    private void button1_Click(object sender, RoutedEventArgs e)
            {
                Thread thread = new Thread(new ThreadStart(StartServer));
                thread.Start();
            }
    
    public void StartServer()
            {
                int port = Convert.ToInt32(GetText(this.tbPort));
                ServerSocket serverSocket = new ServerSocket(port);
                serverSocket.Start();
            }
    
    private delegate string GetTextHandle(Control control);
            private string GetText(Control control)
            {
                if (this.Dispatcher.Thread != System.Threading.Thread.CurrentThread)
                {
                    return (string)this.Dispatcher.Invoke(new GetTextHandle(this.GetText), control);
                }
                else
                {
                    if (control.GetType() == typeof(TextBox))
                    {
                        return ((TextBox)control).Text;
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
            }

    总结:

    由上述几个实例可以看到跨线程调用需要使用Invoke和BeginInvoke(暂时没有用到),在一些要求并不是很严格的系统中,暂且认为二者是可以通用的。(不知道对不?望高手指点一二)

    目前为止,所接触到的常见问题只有这些,以后遇到再补充吧。

  • 相关阅读:
    .NET开发人员如何开始使用ML.NET
    微软开源 Try .NET
    在kubernetes 集群内访问k8s API服务
    微软发布ML.NET 1.0
    现代“十二要素应用”与 Kubernetes
    .NET和Docker ,比翼双飞
    .NET Core 时代已经到了,你准备好了吗
    一份.NET 容器化的调查小结
    容器化时代我们应当选择Kubernetes
    机器学习 ML.NET 发布 1.0 RC
  • 原文地址:https://www.cnblogs.com/ysyn/p/4024815.html
Copyright © 2020-2023  润新知