您的位置:首页 > 产品设计 > UI/UE

在非UI线程中改变UI控件属性的通用方法

2010-10-10 14:23 471 查看
转自:http://www.sunnychen.org/trackback.asp?tbID=124&action=addtb&tbKey=43c0d85c8d6d5dcc018d174276ac098da9245500

在.NET中如需在非UI线程中改变UI控件属性时,CLR会抛出异常,提示无法在非UI线程中更新界面上的控件(Cross-threadoperationnotvalid)。一般情况下有两种解决办法。第一种就是设置Control的静态属性CheckForIllegalCrossThreadCalls为False,如下:

01
public
Form1()
02
{
03
InitializeComponent();
04
Control.CheckForIllegalCrossThreadCalls=
false
;
05
}
06
07
private
void
button1_Click(
object
sender,EventArgse)
08
{
09
Threadthread=
new
Thread(()=>
10
{
11
for
(
int
i=0;i<100000;i++)
12
{
13
label1.Text=i.ToString();
14
label1.Refresh();
15
}
16
});
17
thread.Start();
18
}
另一种办法,就是使用委托,根据控件的InvokeRequired属性判断当前控件的更新操作是否是在另一个线程中。如果是,则使用委托进行方法调用并更新控件。但是这种方法有个缺点,就是需要针对每个控件的属性设置方式创建一些单独的委托和方法,这些委托和方法仅仅是在解决跨线程操作的时候使用。比如,你在另一个线程中需要修改某个label的text时,你就需要创建一个SetLabelText方法,假设你还需要更新TextBox的text,那么你还需要另外创建一个SetTextBoxText方法。

通过下面的委托和方法的定义,我们实现了“一次定义,多次使用”。请看:

viewsource

print?

01
private
delegate
void
ParameterizedControlUpdate(
params
object
[]args);
02
03
private
delegate
void
ControlUpdateDelegate(Componentc,
04
ParameterizedControlUpdatecallback,
05
params
object
[]args);
06
07
private
void
DelegatedControlUpdate(Componentc,
08
ParameterizedControlUpdatecallback,
09
params
object
[]args)
10
{
11
Controltarget=(c
is
Control)?(c
as
Control):
this
;
12
if
(target.InvokeRequired)
13
{
14
ControlUpdateDelegated=DelegatedControlUpdate;
15
target.Invoke(d,
new
object
[]{c,callback,args});
16
}
17
else
18
{
19
callback(args);
20
}
21
}
于是,上面的例子可以改为:

viewsource

print?

01
private
void
button1_Click(
object
sender,EventArgse)
02
{
03
Threadthread=
new
Thread(()=>
04
{
05
for
(
int
i=0;i<100000;i++)
06
{
07
DelegatedControlUpdate(label1,args=>
08
{
09
label1.Text=(
string
)args[0];
10
label1.Refresh();
11
},i.ToString());
12
}
13
});
14
thread.Start();
15
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐