今天闲来无事,研究一下C#中的线程。
以前在winform程序中稍微用过BackGroundWorker组件即线程组件,用起来相对方便一点。一直以为BackGroundWorker只能在winform程序中使用,今天在网上查资料才知道原来BackGroundWorker也可以在控制台程序中使用。
添加命名空间using System.ComponentModel即可。
在控制台程序中使用BackGroundWorker的方法如下:
首先设置属性使进程允许报告进度和支持取消:
BackGroundWorker worker=new BackGroundWorker ();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
给BackGroundWorker类添加事件:
worker.DoWork += new DoWorkEventHandler(MethodDowork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunCompleted);
worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
对各事件的说明如下:
DoWork——当执行BackgroundWorker.RunWorkerAsync方法时会触发该事件,并且传递DoWorkEventArgs参数;
ProgressChanged——操作处理中获得的处理状态变化,通过BackgroundWorker.ReportProgress(int)方法 触发该事件,并且传递ProgressChangedEventArgs,其中包含了处理的百分比;
RunWorkerCompleted ——异步操作完成后会触发该事件,当然如果需要在操作过程中结束可以执行BackgroundWorker.CancelAsync方法要求异步调用中 止,并且在异步委托操作中检测BackgroundWorker.CancellationPending属性如果为true的话,跳出异步调用,同时将 DoWorkEventArgs.Cancel属性设为true,这样当退出异步调用的时候,可以让处理RunWorkerCompleted事件的函数 知道是正常退出还是中途退出。
接着定义MethodDowork、RunCompleted、ProgressChanged函数,具体代码如下:
public class MyClass
{
BackgroundWorker worker = null;
int value = 0;
public string str = null;
public string method()
{
worker.RunWorkerAsync((object)value); //主线程向子线程传递参数value
//Thread.Sleep(5000);
//Cancle();
return str;
}
public MyClass(BackgroundWorker myworker,int myvalue,string str)
{
worker = myworker;
value = myvalue;
this.str = str;
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(MethodDowork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunCompleted);
worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
Console.WriteLine("主线程");
}
private void MethodDowork(object o,DoWorkEventArgs e)
{
int value = (int)e.Argument; //在此获取主线程传递来的参数
for (int i = 1; i < value;i++ )
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
Console.WriteLine(i);
worker.ReportProgress(i);
if (i == 5)
{
e.Result = "Stoped"; //new Exception();
break;
}
Thread.Sleep(1000);
}
}
private void Cancle()
{
worker.CancelAsync();
}
private void RunCompleted(object o, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
Console.WriteLine("Cancled.......");
else if (((string)e.Result).Equals("Stoped"))//is Exception)
Console.WriteLine("Exception........");
else
{
str = "正常结束";
Console.WriteLine("Complete.......");
}
}
private void ProgressChanged(object o, ProgressChangedEventArgs e)
{
Console.WriteLine("ProgressChanged...." + e.ProgressPercentage.ToString());
}
}
然后在主函数中调用
static void Main(string[] args)
{
BackgroundWorker worker = new BackgroundWorker();
string str = "";
MyClass myclass = new MyClass(worker,20,str);
str=myclass.method();
Thread.Sleep(2000);
Console.WriteLine("main program...."+str);
Console.Read();
}
到此,在控制台中使用BackGroundWorker类的用法结束。上述例子也列举了从主线程向子线程传递参数的用法。
主线程向子线程传递参数的方法会了,反过来,当子线程执行完毕的时候如何通知主线程呢?
下面来介绍如何从子线程向主线程发送消息。
首先定义消息类,此类派生于EventArgs,具体代码如下:
public class NewEventArgs : EventArgs
{
public int c = 0;
public string str = null;
public Student stu = new Student();
public NewEventArgs(int cc)
{
c = cc;
}
public NewEventArgs(string name)
{
str = name;
}
public NewEventArgs(Student stu)
{
this.stu = stu;
}
}
然后在MyClass类中定义事件的委托和事件
//事件的委托
public delegate void MessageEventHandler(object sender, NewEventArgs e);
//事件
public event MessageEventHandler MessageSend;
然后在线程函数里的线程执行完毕下面添加发送消息的代码:
this.MessageSend(this, new NewEventArgs(10));
然后在Main函数中添加myclass对象的事件处理,代码如下:
//消息响应函数,输出计算结果
private static void Response(object sender, NewEventArgs e)
{
Console.WriteLine(e.c);
}
在Main函数里添加如下代码:
myclass.MessageSend += new MyClass.MessageEventHandler(Response);
具体代码如下:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
BackgroundWorker worker = new BackgroundWorker();
string str = "";
MyClass myclass = new MyClass(worker,5,str);
myclass.MessageSend += new MyClass.MessageEventHandler(Response);
str=myclass.method();
Console.WriteLine("main program...."+str);
Console.Read();
}
private static void Response(object sender, NewEventArgs e)
{
Console.WriteLine("子线程传递给主线程的消息是:"+e.c);
}
}
public class MyClass
{
BackgroundWorker worker = null;
int value = 0;
public string str = null;
//事件的委托
public delegate void MessageEventHandler(object sender, NewEventArgs e);
//事件
public event MessageEventHandler MessageSend;
public string method()
{
worker.RunWorkerAsync((object)value);
return str;
}
public MyClass(BackgroundWorker myworker,int myvalue,string str)
{
worker = myworker;
value = myvalue;
this.str = str;
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(MethodDowork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunCompleted);
worker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
Console.WriteLine("主线程");
}
private void MethodDowork(object o,DoWorkEventArgs e)
{
int value = (int)e.Argument;
for (int i = 1; i < value;i++ )
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
Console.WriteLine(i);
worker.ReportProgress(i);
Thread.Sleep(1000);
}
this.MessageSend(this, new NewEventArgs(10));
}
private void Cancle()
{
worker.CancelAsync();
}
private void RunCompleted(object o, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
Console.WriteLine("Cancled.......");
else
{
str = "正常结束";
Console.WriteLine("Complete.......");
}
}
private void ProgressChanged(object o, ProgressChangedEventArgs e)
{
Console.WriteLine("ProgressChanged...." + e.ProgressPercentage.ToString());
}
}
//要传递的消息,带有参数c
public class NewEventArgs : EventArgs
{
public int c = 0;
public string str = null;
public Student stu = new Student();
public NewEventArgs(int cc)
{
c = cc;
}
public NewEventArgs(string name)
{
str = name;
}
public NewEventArgs(Student stu)
{
this.stu = stu;
}
}
public class Student
{
public int age;
public string name;
}
}
总结:
子线程向子线程传递消息使用的是事件和委托。