[C#参考]主线程和子线程之间的参数传递
2015-01-10 14:58
281 查看
几个进程在大多数情况下要包含很多的子线程,那么他们之间免不了的要互相传递很多的参数,那么参数怎么传递的呢?
这个Thread类的构造方法的定义如下:
下面的代码使用了这个带参数的委托向线程传递一个字符串参数:
注意这种形式,委托就是Thread要执行的方法,这个委托有一个类的实例对象作为参数。然后在Thread的Start()方法中把这个对象传进去。
如果使用了不带参数的委托,当然也能很正常的启动线程,别学傻了。
第二种方法:定义一个类来传递参数
这种方法的特点是:子线程的执行入口是在另一个类中,这样正好可以借助这个类的成员函数,给子线程传参。
第三种方法:定义一个新的线程类,让所有的子线程类都继承自这个类
其实上面的两种方法的原理是一样的,这是一个面向数据,一个面向线程。
上面的这种情况似乎用不着子线程给UI线程返回数据,反正子线程可以访问主线程的成员变量。但是另一种情况来了,当子线程不再UI线程所在的类的时候,也就是说子线程在一个工具类中,UI类new出来一个工具类完成一定的工作,UI类可以初始化工具类,但是工具类完成了一定任务后怎么通知UI类呢?现在有这种假设:
UI类要Socket连接网络,现在有一个SocketUtil工具可以完成这项任务,所以UI类就New出来一个SocketUtil,然后调用指定的函数,把IP和Port传递进去。在完成了一些任务以后,SocketUtil要反馈一些信息给UI类。让UI类显示反馈的信息。现在面临两个问题:
1.UI类怎么知道SocketUtil完成了这项任务,然后取显示数据呢?
2.UI类即使知道了什么时候显示信息,那么要显示的内容,UI类怎么知道是什么呢?
第一个问题的解决方法就是事件,利用事件就能在SocketUtil完成一些任务之后,通知UI类接下来怎么做。
第二个问题就是利用Invoke让子线程给主线程调用主线程的函数完成任务的时候,给一些参数。
这里就直接在同一个类中展示一下:
这个方法是这样操作的,BeginInvoke可以传递一个数组,这个数组是boject类型的,这样就可以把所有的参数都装箱成object类型的,弄成一个object类型的数组,然后到调用方在拆封就可以了。
主线程向子线程传递参数的方法
第一种方法:Thraed类有一个带参数的委托类型的重载形式,这个委托的定义如下:publicdelegatevoidParameterizedThreadStart(Objectobj)
这个Thread类的构造方法的定义如下:
publicThread(ParameterizedThreadStartstart);
下面的代码使用了这个带参数的委托向线程传递一个字符串参数:
publicstaticvoidmyStaticParamThreadMethod(Objectobj)
{
Console.WriteLine(obj);
}
staticvoidMain(string[]args)
{
Threadthread=newThread(myStaticParamThreadMethod);
thread.Start("通过委托的参数传值");
}
注意这种形式,委托就是Thread要执行的方法,这个委托有一个类的实例对象作为参数。然后在Thread的Start()方法中把这个对象传进去。
如果使用了不带参数的委托,当然也能很正常的启动线程,别学傻了。
第二种方法:定义一个类来传递参数
classProgram
{
staticvoidMain(string[]args)
{
MyDatamyData=newMyData("abcd",1234);
Threadthread=newThread(myData.ThreadMethod);
thread.Start();
Console.ReadKey();
}
}//class
//定义一个类传递参数
publicclassMyData
{
privatestringd1;
privateintd2;
publicMyData(stringd1,intd2)
{
this.d1=d1;
this.d2=d2;
}
publicvoidThreadMethod()
{
Console.WriteLine(d1);
Console.WriteLine(d2);
}
}//class
这种方法的特点是:子线程的执行入口是在另一个类中,这样正好可以借助这个类的成员函数,给子线程传参。
第三种方法:定义一个新的线程类,让所有的子线程类都继承自这个类
abstractclassMyThread
{
Threadthread=null;
abstractpublicvoidrun();
publicvoidStart()
{
if(thread==null)
{
thread=newThread(run);
thread.Start();
}
}
}
classUtility:MyThread
{
privatestringd1;
privateintd2;
publicoverridevoidrun()
{
Console.WriteLine(d1);
Console.WriteLine(d2);
}
}//class
其实上面的两种方法的原理是一样的,这是一个面向数据,一个面向线程。
子线程向主线程传递参数
这里看到是传递参数,也就是说子线程要调用主线程的一个方法,然后把参数传递给主线程的那个方法。说一下方法是前面已经讲过的Invoke和BeginInvoke,但是那时调用主线程的方法并没有传递参数,今天看一下带参数的调用主线程的指定方法。usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Threading;
namespaceWindowsFormsApplication3
{
publicpartialclassForm1:Form
{
privateintcount=0;
privatedelegatevoidDoWorkUIThreadDelegate();
publicForm1()
{
InitializeComponent();
}
privatevoidbtnStart_Click(objectsender,EventArgse)
{
Threadthread=newThread(ThreadMethod);
thread.IsBackground=true;
thread.Start();
}
privatevoidThreadMethod()
{
while(true)
{
//lblResult.Text=DateTime.Now.ToString();
//这句话不能直接调用,因为子线程不能直接调用UI线程中的控件
if(this.InvokeRequired)
{
this.BeginInvoke(newDoWorkUIThreadDelegate(DoWorkUIThread),null);
}
else
{
DoWorkUIThread();
}
//子线程还是可以访问UI线程的普通变量的,只是不能访问控件
//因为普通变量是属于整个类的,属于整个进程的,各个线程时共享的
//对访问共享的数据,加一个lock的锁更加的好
count++;
Thread.Sleep(1000);
}
}
privatevoidDoWorkUIThread()
{
txtTime.Text=DateTime.Now.ToString()+""+count;
}
}
}
上面的这种情况似乎用不着子线程给UI线程返回数据,反正子线程可以访问主线程的成员变量。但是另一种情况来了,当子线程不再UI线程所在的类的时候,也就是说子线程在一个工具类中,UI类new出来一个工具类完成一定的工作,UI类可以初始化工具类,但是工具类完成了一定任务后怎么通知UI类呢?现在有这种假设:
UI类要Socket连接网络,现在有一个SocketUtil工具可以完成这项任务,所以UI类就New出来一个SocketUtil,然后调用指定的函数,把IP和Port传递进去。在完成了一些任务以后,SocketUtil要反馈一些信息给UI类。让UI类显示反馈的信息。现在面临两个问题:
1.UI类怎么知道SocketUtil完成了这项任务,然后取显示数据呢?
2.UI类即使知道了什么时候显示信息,那么要显示的内容,UI类怎么知道是什么呢?
第一个问题的解决方法就是事件,利用事件就能在SocketUtil完成一些任务之后,通知UI类接下来怎么做。
第二个问题就是利用Invoke让子线程给主线程调用主线程的函数完成任务的时候,给一些参数。
这里就直接在同一个类中展示一下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Threading;
namespaceWindowsFormsApplication3
{
publicpartialclassForm1:Form
{
privateintcount=0;
privatedelegatevoidDoWorkUIThreadDelegate(stringname,intid);
publicForm1()
{
InitializeComponent();
}
privatevoidbtnStart_Click(objectsender,EventArgse)
{
Threadthread=newThread(ThreadMethod);
thread.IsBackground=true;
thread.Start();
}
privatevoidThreadMethod()
{
stringstrName="stemon";
intID=1;
while(true)
{
//lblResult.Text=DateTime.Now.ToString();
//这句话不能直接调用,因为子线程不能直接调用UI线程中的控件
if(this.InvokeRequired)
{
object[]myArray=newobject[2];
//类型的装箱是自动的
//类型的拆箱要强制转换
myArray[0]=strName;
myArray[1]=ID;
this.BeginInvoke(newDoWorkUIThreadDelegate(DoWorkUIThread),myArray);
}
else
{
//DoWorkUIThread(strName,ID);
}
//子线程还是可以访问UI线程的普通变量的,只是不能访问控件
//因为普通变量是属于整个类的,属于整个进程的,各个线程时共享的
//对访问共享的数据,加一个lock的锁更加的好
count++;
Thread.Sleep(1000);
}
}
privatevoidDoWorkUIThread(stringname,intid)
{
txtTime.Text=name+""+id+""+DateTime.Now.ToString()+""+count;
}
}
}
这个方法是这样操作的,BeginInvoke可以传递一个数组,这个数组是boject类型的,这样就可以把所有的参数都装箱成object类型的,弄成一个object类型的数组,然后到调用方在拆封就可以了。
相关文章推荐
- C# 同一应用程序域不同线程之间的参数传递方式
- C# 同一应用程序域不同线程之间的参数传递方式
- C# 同一应用程序域不同线程之间的参数传递方式
- 委托与事件的简单应用(不同控件之间的控制及参数传递,C# VB)
- c# winform窗体之间传递参数的几种方法
- C#多线程参数传递.cs
- 陈广老师C#参考视频 方法的参数传递 总结
- C# 给另一线程传递参数
- c# winform窗体之间传递参数问题总结
- c#给线程传递参数的方法
- C# 使用自定义线程类向线程传递参数
- c#线程间传递参数
- C#线程传递参数!!
- C# multithread,threadpool,ParameterizedThreadStart,传递参数给线程以及回调
- c#winform编程 窗体之间传递参数问题总结(转)
- c# 多线程的使用-为线程传递参数
- 一步一步学习C#中的多线程 --- 1、初识线程(2)--给线程传递参数
- android 主线程和子线程之间的消息传递
- C# 线程中使用Timer,并向其触发的事件(函数)中传递参数
- c#用匿名方法传递参数给线程(可不用拆箱和装箱,传任意个参数)【转载】