.net多线程与异步小结

来源:互联网 发布:ubuntu windows双系统 编辑:程序博客网 时间:2024/05/17 08:25

A、Thread,分两种,实例时带入一个委托,System.Threading.ThreadStart是无参数委托,System.Threading.ParameterizedThreadStart是带参数委托,这两个委托都是现成的

不带参数

 Thread thread=new Thread(ThreadStart start);    

带参数

Thread thread=new Thread(ParameterizedThreadStart start);    

 

不带参数例子: 在form的label上刷新当前时间

 

 Thread thread = new Thread(new ThreadStart(() =>            {                while (true)                    this.Invoke(new MethodInvoker(() => { label1.Text = DateTime.Now.ToString(); }));            }));            thread.Start();


 

带参数例子   ParameterizedThreadStart委托带一个object的形参,说明带啥参数都是可以的

  

Thread thread = new Thread(new ParameterizedThreadStart((s) =>            {                while (true)                    this.Invoke(new MethodInvoker(() => { label1.Text = (string)s + DateTime.Now.ToString(); }));            }));            thread.Start("带参数");


 

 

 

 

B、ThreadPool,线程池允许在后台运行多个工作,而不需要为每个任务频繁地创建和销毁单独的线程,从而减少了开销。此类是一个静态类  其静态方法 public static bool QueueUserWorkItem(WaitCallback callBack);用于将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。WaitCallback也是个带object形参的现成委托和ParameterizedThreadStart类似

例子:直接把匿名方法扔进去就开始运行了,只是要注意线程池的可用值,可用即执行。

  

 ThreadPool.QueueUserWorkItem(new WaitCallback((s) =>            {                while (true)                    this.Invoke(new MethodInvoker(() => { label1.Text = (string)s + DateTime.Now.ToString(); }));            }), "带参数"); 


 

 

 

C、异步AsyncCallback  又是一个现成的委托,注意带入形参的类型是IAsyncResult,注意IAsyncResult这个接口下有个object AsyncState { get; } 

 

例子:两个例子的区别只在AsyncState是什么?

1、  

public partial class Form1 : Form    {        delegate void MyHandler(string s);        public Form1()        {            InitializeComponent();            MyHandler handler = new MyHandler((s) =>            {                for (int i = 0; i < 10000; i++)                    this.Invoke(new MethodInvoker(() => { label1.Text = s + i.ToString(); }));            });            AsyncCallback callback = new AsyncCallback(MyCallBack);            handler.BeginInvoke("带参数", callback , handler);  //注意第三个object类型的参数,其实就是AsyncState,所以把handler放进去在回调里显式转换一下就是委托了        }        public void MyCallBack(IAsyncResult ar)     //回调函数,线程处理完执行的方法        {            ((MyHandler)ar.AsyncState).EndInvoke(ar);        }    }


 

 

 2、 

public partial class Form1 : Form    {        delegate void MyHandler(string s);        public Form1()        {            InitializeComponent();            MyHandler handler = new MyHandler((s) =>            {                for (int i = 0; i < 10000; i++)                    this.Invoke(new MethodInvoker(() => { label1.Text = s + i.ToString(); }));            });            AsyncCallback callback = new AsyncCallback(MyCallBack);            handler.BeginInvoke("带参数", callback , "回调完毕"); //此处第三个参数把AsyncState用来传值(或者直接设为null),回调方法里就不一样        }        public void MyCallBack(IAsyncResult ar)     //回调函数,线程处理完执行的方法        {            MyHandler handler = (MyHandler)((AsyncResult)ar).AsyncDelegate;            handler.EndInvoke(ar);            this.Invoke(new MethodInvoker(() => { label1.Text += ar.AsyncState; }));        }    }


 

 

D、由C联想到文件IO的异步、网络的异步,其实大同小异

 文件IO异步例子

 

public partial class Form1 : Form    {        const int bufferSize = 10;             byte[] data = new byte[bufferSize];        List<byte> totalData = new List<byte>();        AsyncCallback callback;        public Form1()        {            InitializeComponent();            FileStream fs = new FileStream("Test.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 10240, true);            callback = new AsyncCallback(MyCallBack);            fs.BeginRead(data, 0, bufferSize, callback, fs); //BeginRead背后的实现其实是这样的:ReadDelegate delegate2 = new ReadDelegate(this.Read);   delegate2.BeginInvoke(buffer, offset, count, callback, state);   多么熟悉            }        public void MyCallBack(IAsyncResult ar)        {            FileStream fs = (FileStream)ar.AsyncState;            int bytesRead = fs.EndRead(ar);            if (bytesRead > 0)            {                fs.BeginRead(data, 0, bufferSize, callback, fs);                totalData.AddRange(data);                Array.Clear(data, 0, bufferSize);            }            else          //读完一起显示            {                this.Invoke(new MethodInvoker(() => { label1.Text = Encoding.Default.GetString(totalData.ToArray()); }));                fs.Close();            }        }    }


网络接收的例子

 public partial class Form1 : Form    {        const int bufferSize = 4096;        byte[] buffer = new byte[bufferSize];        AsyncCallback callback;        public Form1()        {            InitializeComponent();            ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>            {                IPAddress ip = IPAddress.Parse("127.0.0.1");                TcpListener listener = new TcpListener(ip, 8888);                listener.Start();                while (true)          //循环处理,可以同时支持多个client                {                    TcpClient client = listener.AcceptTcpClient();                    NetworkStream stream = client.GetStream();                    callback = new AsyncCallback(MyCallBack);                    stream.BeginRead(buffer, 0, bufferSize, callback, client);//最后一个参数把TcpClient放进去,回调中就可以分别处理不同的Client了                }            }));        }        public void MyCallBack(IAsyncResult ar)        {            TcpClient client = (TcpClient)ar.AsyncState;                //把TcpClient取出来,AsyncState真是好东西            NetworkStream stream = client.GetStream();            int bytesRead = stream.EndRead(ar);            try            {                if (bytesRead > 0)   //有数据                {                    this.Invoke(new MethodInvoker(() => { label1.Text += Encoding.Unicode.GetString(buffer, 0, bytesRead); }));                    Array.Clear(buffer, 0, buffer.Length);                }                stream.BeginRead(buffer, 0, bufferSize, callback, client);            }            catch (Exception)            {                if (stream != null)                    stream.Dispose();                client.Close();            }        }    }


为了方便上面程序调试给个发送数据的例子

static void Main(string[] args)        {            TcpClient client;            try            {                client = new TcpClient();                client.Connect("localhost", 8888);                while (true)                {                    string msg = Console.ReadLine();                    NetworkStream stream = client.GetStream();                    byte[] buffer = Encoding.Unicode.GetBytes(msg);                    stream.Write(buffer, 0, buffer.Length);                    Console.WriteLine("发送: {0}", msg);                }            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }        }

E、BackgroundWorker    也是用来执行多线程任务的一个控件,其有三个事件,用起来比较优雅,也经常配合进度条使用,ReportProgress会触发ProgressChanged事件,从而实现进度刷新

BackgroundWorker worker = new BackgroundWorker();            worker.WorkerReportsProgress = true;  //报告进度            worker.DoWork += (sender, e) =>            {                for (int i = 0; i <= 10000; i++)                    this.Invoke(new MethodInvoker(() => { label1.Text = i.ToString(); worker.ReportProgress(i / 100, null); }));            };            worker.RunWorkerCompleted += (sender, e) =>            {                this.Invoke(new MethodInvoker(() => { label1.Text += "执行完毕"; }));            };            worker.ProgressChanged += (sender, e) =>            {                progressBar1.Style = ProgressBarStyle.Continuous;                progressBar1.Value = e.ProgressPercentage;            };            worker.RunWorkerAsync();



55 0
原创粉丝点击