如何在多线程中调用winform窗体控件
2008-11-19 10:49
411 查看
如何在多线程中调用winform窗体控件
由于 Windows 窗体控件本质上不是线程安全的。因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用和死锁的情况。于是在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException
本文用一个很简单的示例来讲解这个问题(在窗体上放一个TextBox和一个Button,点击Button后,在新建的线程中设置TextBox的值)
解决办法一: 关闭该异常检测的方式来避免异常的出现
经过测试发现此种方法虽然避免了异常的抛出,但是并不能保证程序运行结果的正确性 (比如多个线程同时设置TextBox1的Text时,很难预计最终TextBox1的Text是什么)
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Text;
7
using System.Windows.Forms;
8
using System.Threading;
9
10
namespace 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
}
解决办法二:通过委托安全调用
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Text;
7
using System.Windows.Forms;
8
9
namespace 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控件
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Text;
7
using System.Windows.Forms;
8
using System.Threading;
9
10
namespace 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
}
posted @ 2007-12-20 16:50 菩提树下的杨过 阅读(280) 评论(0) 编辑 收藏 网摘
相关文章推荐
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件(转)
- 如何在多线程中调用winform窗体控件(续)
- 转:如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件
- 如何在多线程中调用winform窗体控件2――实例篇
- c#中跨线程调用windows窗体控件 .我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。
- C# winform中一个类中如何调用另一个窗体的控件或方法
- winform 利用 多线程 处理窗体假死,利用 Invoke BeginInvoke 处理子线程调用 UI 控件报错的问题
- 在多线程中调用winform窗体控件的实现方法
- WinForm异步:如何:对 Windows 窗体控件进行线程安全调用
- C# winform中一个类中如何调用另一个窗体的控件或方法
- Windows 窗体控件中的多线程处理之:如何对 Windows 窗体控件进行线程安全调用
- 在多线程中如何调用Winform