C#跨線程操做控件

在看別人代碼的時候老是會Invoke和BeginInvoke方法,雖然大體明白是什麼意思,但卻不能很好的使用,上網查了不少資料,剛巧看到本身求學期間轉載過一篇博文:html

c#Invoke和BeginInvoke的區別c#

 博文中講的都是一些理論知識,本文介紹幾個常見的問題:異步

 .net平臺下Winform、wpf禁止跨線程直接訪問控件,所以在必須跨線程訪問控件的時候採用異步方式。socket

 

一、winform項目中跨線程訪問控件:ui

  編寫一個Winform小實例:在作winform項目中,有時爲了將系統運行的狀態實時顯示到Form中,所以添加一個RichTextbox控件實時顯示系統運行日誌。本例實現的操做是將日誌以字符串的形式寫入RichTextbox控件,由於是實時顯示,因此涉及到跨線程輸入的問題。this

    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時,說明有一個不屬於建立它的線程要訪問它,此時須要採用異步的方式進行操做。spa

能夠改進:.net

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);
            }
        }

 

 

二、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);

        }

 

三、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(暫時沒有用到),在一些要求並非很嚴格的系統中,暫且認爲兩者是能夠通用的。(不知道對不?望高手指點一二)

目前爲止,所接觸到的常見問題只有這些,之後遇到再補充吧。

相關文章
相關標籤/搜索