.net多线程与异步小结

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();



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值