zoukankan      html  css  js  c++  java
  • 【编写高质量代码C#】建议71:区分异步和多线程应用场景

    1.在获取网页内容的时候,可能由于网络不好,获取时间会很长,这时候我们一般会使用新建一个线程去获取,这样在获取网页的这段时间中,主线程就不会阻滞了。

            private void btnGetPage_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(() =>
                {
                    //没有下面这一行会报线程无效的异常
                    //设置是否捕获对错误线程的调用,调用时会访问应用程序空间的属性
                    Control.CheckForIllegalCrossThreadCalls = false;
                    var req = HttpWebRequest.Create("http://www.sina.com.cn");
                    var resp = req.GetResponse();
                    Stream stream = resp.GetResponseStream();
                    using (StreamReader sr=new StreamReader(stream,Encoding.UTF8))
                    {
                        textBox1.Text = sr.ReadToEnd();
                    }
                });
                th.Start();
            }
    

    上面的例子解决了主线程可能被阻滞的问题,但是新建的获取网页的线程一直在占用系统的资源,显然是不高效的。接下来,我们考虑用异步模式去实现。

    2.异步模式获取网页内容

            private void btnGetPage2_Click(object sender, EventArgs e)
            {
                var req = (HttpWebRequest)HttpWebRequest.Create("http://www.sina.com.cn");
                //开始对Internet资源的异步请求
                req.BeginGetResponse(AsyncCallbackImpl, req);
    
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="ar">异步操作的状态</param>
            public void AsyncCallbackImpl(IAsyncResult ar)
            {
                //获取异步请求
                WebRequest webreq = ar.AsyncState as WebRequest;
                
                var resp = webreq.EndGetResponse(ar);
                var stream2 = resp.GetResponseStream();
                using (StreamReader sr = new StreamReader(stream2))
                {
                    var strdocument = sr.ReadToEnd();
                    //调用方调用控件方法时是否必须调用Invoke方法,因为调用方线程在控件线程以外
                    if (textBox2.InvokeRequired)
                    {
                        //1. 委托使用
                        //del d=NewMethod;
                        //textBox2.Invoke(d,strdocument);
    
                        //2. 直接使用new Action()
                        textBox2.Invoke(new Action(() =>
                        {
                            textBox2.Text = strdocument;
                        }));
                    }
                    else
                    {
                        textBox2.Text = strdocument;
                    }
    
                    if (textBox1.InvokeRequired)
                    {
                        textBox1.Invoke(new Action(() => { 
                        
                        }));
                    }
                }
            }
    

      采用异步模式,它使用线程池进行管理。这时候获取网页就不会占用任何CPU了,更高效!

    3.多线程和和异步分别在怎样的应用场景中使用?

    从上例子可以分析得到:

    在计算密集型工作中应考虑使用多线程,避免线程阻滞;在I/O密集型工作中应考虑使用异步模式,减少CPU占用。

  • 相关阅读:
    设置ActiveMQ的访问密码
    Java NIO SocketChannel套接字通道
    Java 8 基础API的一些小的该进
    Java 8 异常该进
    Java NIO Channel to Channel Transfers通道传输接口
    Java NIO Scatter / Gather
    mysql分表经验总结
    Java 8 Optional类深度解析(转)
    Java 8 文件操作(转)
    使用 Java8 Optional 的正确姿势(转)
  • 原文地址:https://www.cnblogs.com/Med1tator/p/6431452.html
Copyright © 2011-2022 走看看