C#中的线程

来源:互联网 发布:processon mac 下载 编辑:程序博客网 时间:2024/06/05 03:07

今天闲来无事,研究一下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;
    }

}

总结:

     子线程向子线程传递消息使用的是事件和委托。