今天就来学习一下C#中的线程和进程的问题吧
在C#中要操作线程就要借助Thread这个类来进行的一些操作的,首先要事例化一个thread的类,再在这个类的基础上进行操,在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
下面给出一个多线程的操作问题的例子:
public class Test
{
static public void ShowInfo()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("1线程输出的信息");
Thread.Sleep(100);
}
}
public static void Main(string[] argvs)
{
Thread myThread = new Thread(new ThreadStart(Test.ShowInfo));
myThread.Start();
for (int i = 0; i < 10; i++ )
{
Console.WriteLine("主线程执行完毕!");
Thread.Sleep(100);
}
Console.ReadKey();
}
}
这个例子中是将主函数作为一个主线程,定义一个新的线程myThread 的线程,然后通过Start方法来开始该线程的。当然在实例化这个线程的时候我们要传入一个委托Test.ShowInfo作为参数。通过这个委托来将具体的方法给实现的。
执行结果如下图所示:
当然,每次的执行的结果是不一样的,这个是和电脑的CPU的线程调度有关系的。
对于多线程,很多的时候是有数据的交换的,比如说数据的传入和数据的传出,但是在都线程中是怎么传入参数的呢,当然如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。
为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。
下面就是一个例子,在启动线程时指定了线程的名字,代码如下
对于多线程,很多的时候是有数据的交换的,比如说数据的传入和数据的传出,但是在都线程中是怎么传入参数的呢,当然如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。
为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。
下面就是一个例子,在启动线程时指定了线程的名字,代码如下
static public void ShowInfo(object threadName)
{
string name = threadName as string;
for (int i = 0; i < 5; i++ )
{
Console.WriteLine("{0}在执行!\n", threadName);
Thread.Sleep(100);
}
}
public static void Main(string[] argvs)
{
Thread myThread = new Thread(new ParameterizedThreadStart(Test.ShowInfo));
myThread.Name = "子线程";
myThread.Start(myThread.Name);
ShowInfo("主线程");
Console.ReadKey();
}
运行结果如下图所示
当然这个例子只是实现了传入一个参数的例子,但是,很多的时候,我们会要传入很多个参数的,但是这个时候我们要怎么做额。前面已经介绍了,在用ParameterizedThreadStart它来进行初始化一个线程的时候,可以传入一个object的类型,我们都知道,object几乎是可以和任何的类型进行转化的,这个时候我们就会想到要引入一个外部类来实现传入多个参数的问题。
下面通过一个例子来演示通过引入外部类的方法来传入多个参数的具体实现:
namespace StartThread
{
class MyThreadParameter
{
private int interval;
private int loopCount;
/// <summary>
/// 循环次数
/// </summary>
public int LoopCount
{
get { return loopCount; }
}
/// <summary>
/// 线程的暂停间隔
/// </summary>
public int Interval
{
get { return interval; }
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="interval">线程的暂停间隔</param>
/// <param name="loopCount">循环次数</param>
public MyThreadParameter(int interval, int loopCount)
{
this.interval = interval;
this.loopCount = loopCount;
}
}
class Program
{
int interval = 200;
static void Main(string[] args)
{
Program p = new Program();
Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun));
parameterThread.Name = "Thread A:";
MyThreadParameter paramter = new MyThreadParameter(50, 20);
parameterThread.Start(paramter);
Console.ReadKey();
}
/// <summary>
/// 带多个参数的启动方法
/// </summary>
/// <param name="ms">方法参数</param>
public void MyParameterRun(object ms)
{
MyThreadParameter parameter = ms as MyThreadParameter;//类型转换
if (parameter != null)
{
for (int i = 0; i < parameter.LoopCount; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
Thread.Sleep(parameter.Interval);//让线程暂停
}
}
}
}
}
运行结果如下图所示
当然还有另外的一种方法,那个方法也是要引入外部类的东西的,但是具体的线程的创建和线程的执行都是在这个类中进行的操作的,具体的实现这里就不上例子了,大家可以思考一下。