程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 如何在多線程中調用winform窗體控件

如何在多線程中調用winform窗體控件

編輯:.NET實例教程

由於 Windows 窗體控件本質上不是線程安全的。因此如果有兩個或多個線程適度操作某一控件的狀態(set value),則可能會迫使該控件進入一種不一致的狀態。還可能出現其他與線程相關的 bug,包括爭用和死鎖的情況。於是在調試器中運行應用程序時,如果創建某控件的線程之外的其他線程試圖調用該控件,則調試器會引發一個 InvalidOperationException 

本文用一個很簡單的示例來講解這個問題(在窗體上放一個TextBox和一個Button,點擊Button後,在新建的線程中設置TextBox的值)

解決辦法一: 關閉該異常檢測的方式來避免異常的出現

經過測試發現此種方法雖然避免了異常的拋出,但是並不能保證程序運行結果的正確性 (比如多個線程同時設置TextBox1的Text時,很難預計最終TextBox1的Text是什麼)


 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Data;
 5using System.Drawing;
 6using System.Text;
 7using System.Windows.Forms;
 8using System.Threading;
 9
10namespace winformTest
11{
12    public partial class Form1 : Form
13    {
14        public Form1()
15        {
16            InitializeComponent();
17            Control.CheckForIllegalCrossThreadCalls = false;//這一行是關鍵      
18        }
19        
20
21        private void button1_Click(object sender, EventArgs e)
22        {
23            SetTextBoxValue();
24        }
25
26        void SetTextBoxValue()
27        {
28            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method1");
29            ThreadStart TS = new ThreadStart(tbsv.SetText);
30            Thread T = new Thread(TS);
31            T.Start();
32        }
33
34
35        class TextBoxSetValue
36        {
37            private TextBox _TextBox ;
38            private string _Value;
39
40            public TextBoxSetValue(TextBox TxtBox, String Value) 
41            {
42                _TextBox = TxtBox;
43                _Value = Value;
44            }
45
46            public void SetText() 
47            {
48                _TextBox.Text = _Value;
49            }
50        }
51    }
52}
解決辦法二:通過委托安全調用

 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Data;
 5using System.Drawing;
 6using System.Text;
 7using System.Windows.Forms;
 8
 9namespace winformTest
10{
11    public partial class Form2 : Form
12    {
13        public Form2()
14        {
15            InitializeComponent();
16        }
17 
18
19        private void button1_Click(object sender, EventArgs e)
20        {
21            SetTextBoxValue();
22        }        
23
24       
25        private delegate void CallSetTextValue();
26        //通過委托調用
27        void SetTextBoxValue() 
28        {
29            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method2");
30            if (tbsv.TextBox.InvokeRequired)
31            {
32                CallSetTextValue call = new CallSetTextValue(tbsv.SetText);
33                tbsv.TextBox.Invoke(call);               
34            }
35            else
36            {
37                tbsv.SetText();
38            }
39        }
40
41
42        class TextBoxSetValue
43        {
44            private TextBox _TextBox;
45            private string _Value;
46
47            public TextBoxSetValue(TextBox TxtBox, String Value)
48            {
49                _TextBox = TxtBox;
50                _Value = Value;
51            }
52
53            public void SetText()
54            {
55                _TextBox.Text = _Value;
56            }
57
58
59            public TextBox TextBox {
60                set { _TextBox = value; }
61                get { return _TextBox; }
62            }           
63        }
64    }
65}

第三解決辦法:利用BackgroundWorker控件

 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Data;
 5using System.Drawing;
 6using System.Text;
 7using System.Windows.Forms;
 8using System.Threading;
 9
10namespace winformTest
11{
12    public partial class Form3 : Form
13    {
14        public Form3()
15        {
16            InitializeComponent();
17        }
18
19        private void button1_Click(object sender, EventArgs e)
20        
21            using (BackgroundWorker bw = new BackgroundWorker())
22            {
23                bw.RunWorkerCompleted += SetTextBoxValue;
24                bw.RunWorkerAsync();
25            }
26        } 
27        
28        void SetTextBoxValue(object sender, RunWorkerCompletedEventArgs e) 
29        {
30            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method3");
31            tbsv.SetText();
32        }
33
34
35        class TextBoxSetValue
36        {
37            private TextBox _TextBox;
38            private string _Value;
39
40            public TextBoxSetValue(TextBox TxtBox, String Value)
41{
42                _TextBox = TxtBox;
43                _Value = Value;
44            }
45
46            public void SetText()
47            {
48                _TextBox.Text = _Value;
49            }
50        }
51
52    }
53
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved