在WinFrom应用中,如果使用后台线程来操作界面应调用Control.Invoke()方法

在WinFrom应用中,如果需要执行一个较长的时间的调用,或要使用Web Serives从服务器取一些数据,我们通常都会使用多线程来实现这个操作,等操作完成后,再来修改一下一些控件的状态.例如下面的代码,当点击按钮,按钮和文本框都将灰化,操作完成后,再在回调函数中将按钮和文本框设为可用.
None.gif using  System;
None.gif
using  System.Drawing;
None.gif
using  System.Threading;
None.gif
using  System.Windows.Forms;
None.gif
None.gif
class  App 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
public static void Main() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Application.Run(
new MultiThreadedForm());
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class  MultiThreadedForm : Form
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
public MultiThreadedForm() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif        
// Create a textbox
InBlock.gif
        text.Location = new Point(1010);
InBlock.gif        text.Size 
= new Size(5020);
InBlock.gif        Controls.Add(text);      
InBlock.gif
InBlock.gif        
// Create a button
InBlock.gif
        button.Text = "Beep";
InBlock.gif        button.Size 
= new Size(5020);
InBlock.gif        button.Location 
= new Point(8010);
InBlock.gif
InBlock.gif        
// Register Click event handler
InBlock.gif
        button.Click += new EventHandler(OnClick); 
InBlock.gif
InBlock.gif        Controls.Add(button);
ExpandedSubBlockEnd.gif    }
    
InBlock.gif
InBlock.gif    
void OnClick(Object sender, EventArgs args) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        EnableControls(
false);
InBlock.gif        Thread myThreading 
= new Thread(new System.Threading.ThreadStart(CallBack));
InBlock.gif        myThreading.Start();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
InBlock.gif    
void CallBack()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// DoSomething();
InBlock.gif        
//System.Threading.Thread.Sleep(5000);
InBlock.gif        
//MessageBox.Show("OK");
InBlock.gif
        EnableControls(true);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
void EnableControls(Boolean enable) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        button.Enabled 
= enable;
InBlock.gif        text.Enabled 
= enable;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    Button  button 
= new Button();
InBlock.gif    TextBox text 
= new TextBox();
ExpandedBlockEnd.gif}

None.gif
None.gif

上面的代码通常是可以正常运行的,但是存在一个潜在的问题,回调方法并不与调用代码在相同的线程上运行,这意味着它可能会在执行应用程序另一部分的同时执行.为了避免这个问题,就需要在访问可能被程序部分使用的对象时使用同步(如lock),但这种锁定控制而进行独占访问并不是合适,反而会导致系统产生更多的问题,这时我们需要使用Control.Invoke()方法.
  Invoke()方法定义在System.Windows.Forms.Control,所有从Ssytem.Windows.Forms.Control继承的类包括From都有这个方法.众所周知,WinFrom的类库是在Win32 API的基础上实现的,而Invoke()方法在底层是用PostMessage函数来实现的,就是说调用Invoke()方法相当于向目标对象只是发送一个消息,对Control的操作还是由用户界面线程来完成,所以这个方法是线程安全的.对以上的代码,只要进行一些修改
 //声明一个委托
delegate BooleanCallBack(bool enable);
void BooleanCallBack enableControls;
//在构造函数中初始化
enableControls = new BooleanCallBack(EnableControls);
// 在CallBack中将EnableControls(true)改为
Invoke(enableControls,new object[]{true});

建一个帮助类
None.gif public   class  Updater
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
private TextBox textBox;
InBlock.gif    
private Button button;
InBlock.gif    
private bool enabled;
InBlock.gif
InBlock.gif    
public Updater(TextBox textbox, Button button, bool enabled)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.textBox = textbox;
InBlock.gif        
this.button = button;
InBlock.gif        
this.enabled = enabled;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public void Update()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.textBox.Enabled = enabled;
InBlock.gif        
this.button.Enabled = enabled;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

然后在CallBack函数中将EnableContrls(true)改为
//创建一个Updater对象
Updater updater = new Updater(this.text, this.button, true);
//调用Invoke()方法
Invoke(new MethodINvoker(updater.Update));
进行了这样的处理,多线程对用户界面的操作应该是线程安全的了.

转载于:https://www.cnblogs.com/PengNian/archive/2004/12/02/72258.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值