★ .Net2.0中通过委托和事件进行线程安全的控件访问
来源:互联网 发布:mysql 注入攻击 编辑:程序博客网 时间:2024/05/01 08:59
在Framework2.0中,跨线程进行访问控件时,编译器会检查你所使用的方法是否线程安全。如VS2003那样直接无视线程赋值和取值的话,编译器会报错,提示线程不安全。几乎所有初次接触多线程WINFORM编程的人都碰到过这样的问题。
发生这类情况的时候,就可以使用委托和事件来回调创建该控件的线程中的方法。
所有控件都继承自 System.Windows.Form.Control类,而在Control类中已经包含了一系列线程安全的解决方案。
Control.InvokeRequired:
判断该该控件是否为当前的线程所创建的。
Control.Invoke(delegate, object [] params):
到创建该控件的线程中去调用委托所决定的方法。因为是委托,所以可以连续调用多个方法。
Control.BeginInvoke() & Control.EndInvoke():
异步方式执行操作,MSDN中有详细的方法
跨线程读取:
对于值类型的变量,跨线程的访问不存在安全问题。但对于引用类型,比如String类型,特别是继承自Control类的控件来说,JIT会抛出类型不安全的异常,解决方法是将需要的值从控件中取出放在值类型中,有两种方法实现:
1、在线程开始之前把数据写入值变量。
2、使用委托去读取控件的值。
以下举例说明
...{
private string[] _file;
public string[] Files
...{
get ...{ return this._file }
set ...{ this._file = value; }
}
public ThreadDemo1() ...{/**//*Constructor*/}
public void Run()
...{
foreach(string strItem in _file)
...{
Console.WriteLine( strItem );
Thread.Sleep(1000);
}
}
}
public delegate string GetStrHandler(int index); //定义委托
class ThreadDemo2
...{
private int _nums;
public int Count
...{
get ...{ return this._nums; }
set ...{ this._nums = value; }
}
public event GetStrHandler onPrint; //定义onPrint事件
public ThreadDemo2() ...{/**//*Constructor*/}
public void Run()
...{
for (int i = 0; i < this._nums; i++ )
...{
Console.WriteLine( this.onPrint(i) ); //输出的同时触发事件
Thread.Sleep(1000);
...{
}
}
/**//**
*主窗体类
*//
class MainForm: Form
...{
//Some Form Initialization Code
//Button button1;
//Button button2;
//ListView lvItems;
//...............................................
private ThreadDemo1 td;
private ThreadDemo2 dtd;
private GetStrHandler GetStr;
//方法一,取值
public button1_Click(object sender, EventAvgs e)
...{
td = new ThreadDemo1();
td.Files = new string[lvItems.Itmes.Count];
foreach(ListViewItem Item in lvItems.Items)
...{
int index = Item.index;
td.Files[index] = new string(Item.Text); //创建新字符串,避免引用
}
Thread myThread = new Thread(new ThreadStart(td.Run));
myThread.Start();
}
//方法二,触发事件
public button2_Click(object sender, EventAvgs e)
...{
dtd = new ThreadDemo2();
dtd.onPrint += this.sendmsg();
Thread myThread = new Thread(new ThreadStart(dtd.Run));
myThread.Start();
}
private string sendmsg(int index)
...{
string Result = String.Empty;
if ( lvItems.InvokeRequired ) //判断是否需要使用Invoke方法,如果当前线程不是控件的创建线程,返回True
...{
GetStr = new GetStrHandler(this.sendmsg);
lvItems.Invoke( GetStr, new objcet[] ...{ index } );
}
else
...{
Result = lvItems.Items[index].Text;
}
return Result;
}
}
将以上代码中的sendmsg方法修改一下,就可以实现跨线程修改控件属性。比如:
...{
if ( lvItems.InvokeRequired ) //判断是否需要使用Invoke方法,如果当前线程不是控件的创建线程,返回True
...{
GetStr = new GetStrHandler(this.setmsg);
lvItems.Invoke( GetStr, new objcet[] ...{ index } );
}
else
...{
lvItems.Items[index].Text = "跨线程修改成功";
}
return Result;
}
这个例子只是简单的使用了委托和事件的基本特性演示了跨线程访问控件的方法。
虽然控件BackgroundWork提供了一种更简便的方法来进行后台任务(就是多线程),但是通过委托和事件可以定制非常复杂的多线程应用。
<iframe src="http://aosustudio.com.cn/ad/GoogleSerch.htm" frameborder="0" width="100%" scrolling="no" height="30"></iframe>
- ★ .Net2.0中通过委托和事件进行线程安全的控件访问
- .Net2.0中通过委托和事件进行线程安全的控件访问
- C#线程中安全访问控件(重用委托,避免繁复的delegate,Invoke)总结
- C#线程中安全访问控件(重用委托,避免繁复的delegate,Invoke)总结
- wpf 委托 Action 通过线程和委托制作时间控件
- 通过按钮事件如何访问datalist中控件的内容
- Winform中使用委托实现跨线程安全调用控件
- C#中跨线程访问控件:委托,Invoke,BeginInvo
- C#中跨线程访问控件: 委托, Invoke, BeginInvoke
- c# winform 通过线程和委托制作时间控件
- c# wpf 通过线程和委托制作时间控件
- ASP.NET2.0 新控件 TreeView控件的属性和事件
- C# Winform项目中多线程环境下, 如何跨线程对Window窗体控件进行安全访问?
- asp.net2.0新增加的安全控件
- asp.net2.0新增加的安全控件
- asp.net2.0新增加的安全控件(译)
- 使用MethodInvoker委托进行跨线程访问
- C#利用委托进行多线程访问控件
- addteach aspx
- ★ asp.net中的联动菜单
- 解析CGI
- addteach cs 2
- ★ 程序员面试攻略
- ★ .Net2.0中通过委托和事件进行线程安全的控件访问
- ★ 流行的Ajax应用演示和源码下载
- 配置JDK与Tomcat
- E1知识
- Java2游戏编程读书笔记(11-2)
- .Net 技术文章转帖
- 如何学好编程
- 从本体的发展看图书情报学
- Web Services开发体会和项目教训