当前位置:编程学习 > wap >>

技术分享 - Windows Phone的异步模型

为了不阻塞UI,在windows的多线程上完全去掉了同步的模型,全部使用异步模型来处理请求。
这样带来的好处是UI不会被卡死,能够一直响应用户的响应,将比较耗时的操作丢给后台线程处理,并且能避开线程同步的麻烦。
但这样一来,写出来的代码也比较难看,还可能涉及到数据共享的问题。
我相信如果你的应用涉及到HttpRequest的话那么一定会遇到我说的情况。
欢迎大家一起讨论你的思路。

以下是几种我常用的异步请求代码的模型
1、使用匿名函数,有时候为了节约会使用lamda表达式
2、事件模式,通过订阅请求完成事件
3、Async CTP

第一种方式的代码如下:

 private string Reqest()
        {
            string resultString = string.Empty;
            HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com");
            request.Method = "GET";
            request.BeginGetResponse((IAsyncResult result) => 
            {
                HttpWebRequest webRequest = result.AsyncState as HttpWebRequest;
                HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(result);
                Stream streamResult = webResponse.GetResponseStream();
                StreamReader reader = new StreamReader(streamResult);

                //获取的返回值
                resultString = reader.ReadToEnd();

            }, request);

            return resultString;
        }


第二种方式的代码如下:

public delegate void GetResultEventHandler(object sender, string e);
        public event GetResultEventHandler OnGetInfoCompleted;

        private void Reqest()
        {
            HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com");
            request.Method = "GET";
            request.BeginGetResponse(GetInfoCompleted, request);

        }

        protected void GetInfoCompleted(IAsyncResult asyncResult)
        {
            try
            {
                HttpWebRequest webRequest = asyncResult.AsyncState as HttpWebRequest;
                HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
                Stream streamResult = webResponse.GetResponseStream();
                StreamReader reader = new StreamReader(streamResult);

                //获取的返回值
                string resultString = reader.ReadToEnd();

                if (OnGetInfoCompleted != null)
                {
                    OnGetInfoCompleted(this, resultString);
                }
            }
            catch (WebException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


第三种方式的代码实现如下:

        private async resultString Reqest()
        {
            HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com");
            request.Method = "GET";
            HttpWebResponse webResponse = await request.GetResponseAsync();
            Stream streamResult = response.GetResponseStream();
            StreamReader reader = new StreamReader(streamResult, new GB2312.GB2312Encoding());
            string resultString = reader.ReadToEnd();

            return resultString;


        }


因为有时候请求会有嵌套关系,比如在请求第二个数据之前,需要先请求第一个数据,所以用第一种方式会一直匿名很多层,让我觉得很不爽。
在没有async CTP for windows phone之前,我一直用第二种方式来写代码,因为这样逻辑比较清楚。只是事件的模型看起来也不完美,但这也算是比较常用的异步模型,用事件来传递参数。缺点是当逻辑需要阻塞线程的时候,却又阻塞不了。
我想这也是async框架出现的原因吧。
在windows8的开发中,async框架已成为正式版,也就是说已经完全支持了第三种异步模型,也就是以async,await为主导的模型。这样即可以让需要等待的代码阻塞着,又可以让UI线程保持通畅,并且代码的逻辑也能很清楚,又避开了线程同步的数据锁的麻烦。
算是在这件事情上现阶段较为完美的方案了。

抛砖引玉,大家积极讨论。

顺便庆祝升星,炎热的夏天,散点分。 --------------------编程问答-------------------- nice!

........... --------------------编程问答-------------------- 学习了 --------------------编程问答-------------------- 我都是用第二种方式  第三种方式第一次见  学习了 --------------------编程问答-------------------- 谢版主分享。
最近超热心。 --------------------编程问答-------------------- --------------------编程问答-------------------- 挺好的  不错
--------------------编程问答-------------------- 挺好的   不错
--------------------编程问答-------------------- 学习了 感谢分享~ --------------------编程问答-------------------- 多谢分享  --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 大家积极讨论。 --------------------编程问答-------------------- 大家积极讨论。 --------------------编程问答-------------------- 学习了,虽然还看不懂 --------------------编程问答-------------------- 学习了,感谢楼主分享! --------------------编程问答-------------------- 好好看看 --------------------编程问答-------------------- 谢谢分享,收藏了 --------------------编程问答--------------------

谢谢分享! --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 你回答的很不错呀 --------------------编程问答-------------------- 好贴  学习了 --------------------编程问答-------------------- --------------------编程问答-------------------- 学习了
--------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 楼主,第3种是属于同步吧. --------------------编程问答-------------------- --------------------编程问答-------------------- Ultimate Toolbox --------------------编程问答-------------------- 好东西! --------------------编程问答-------------------- --------------------编程问答-------------------- 没又wp --------------------编程问答-------------------- 不对吧 你的程序 --------------------编程问答-------------------- 谢谢楼主哈!!!!!! --------------------编程问答-------------------- 谢谢楼主哈!!!!!!! --------------------编程问答-------------------- 谢谢 楼主 哈啊 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 谢谢分享··· --------------------编程问答-------------------- 感谢楼主分享! --------------------编程问答-------------------- 学习了,多谢楼主 --------------------编程问答-------------------- 学习了,多谢楼主 --------------------编程问答-------------------- --------------------编程问答-------------------- 学习了,多谢楼主 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 支持了,谢谢楼主的分享 --------------------编程问答-------------------- 楼主不知道能否提供的同步版的,就要同步的,不要异步的。
http://topic.csdn.net/u/20120713/17/2cfca3fe-a527-4c6c-a397-288629bccbce.html?seed=1733111358&r=79148395#r_79148395
我这个帖子你回复了下,但是,我还是要同步的,你这三个方法都是异步的。 --------------------编程问答-------------------- 顶,好贴 --------------------编程问答--------------------
引用 57 楼  的回复:
楼主不知道能否提供的同步版的,就要同步的,不要异步的。
http://topic.csdn.net/u/20120713/17/2cfca3fe-a527-4c6c-a397-288629bccbce.html?seed=1733111358&r=79148395#r_79148395
我这个帖子你回复了下,但是,我还是要同步的,你这三个方法都是异步的。


我不知道你的具体流程和需求,我认为多数情况下,第三种方法应该能满足想达到同步的要求。
你能描述一下你的流程和需求吗? --------------------编程问答--------------------
引用 59 楼  的回复:
引用 57 楼  的回复:
楼主不知道能否提供的同步版的,就要同步的,不要异步的。
http://topic.csdn.net/u/20120713/17/2cfca3fe-a527-4c6c-a397-288629bccbce.html?seed=1733111358&r=79148395#r_79148395
我这个帖子你回复了下,但是,我还是要同步的,你这三个方法都是……


第三种我试了下,request.GetResponseAsync(); 这个东西,貌似在wp7下没法用,没有这个方法GetResponseAsync

我要同步的方法。我的需求是,比如说:我先抓百度的数据,百度没有再抓谷歌的。
这时候我就要判断,
string html = Helper.LoadHtml("http://www.baidu.com");
if(string.IsNullOrEmpty(html))
{
         html = Helper.LoadHtml("http://www.google.com");
}
--------------------编程问答--------------------
引用 60 楼  的回复:
引用 59 楼 的回复:

引用 57 楼 的回复:
楼主不知道能否提供的同步版的,就要同步的,不要异步的。
http://topic.csdn.net/u/20120713/17/2cfca3fe-a527-4c6c-a397-288629bccbce.html?seed=1733111358&r=79148395#r_79148395
我这个帖子你回复了下,但……

你需要下载这个sdk (sync ctp v3)
http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=9983
才可以使用async/await,也才相应地有那些后缀为async的方法

如果用第三种方法,你可以用await的方式抓取百度的数据,而后再抓取google的数据。
像这样:

string html = await Helper.LoadHtml("http://www.baidu.com");
if(string.IsNullOrEmpty(html))
{
         html = await Helper.LoadHtml("http://www.google.com");
}

但是你需要将你的helper类的LoadHtml方法加以async签名。 --------------------编程问答-------------------- 好贴,先顶 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 61 楼  的回复:
引用 60 楼  的回复:
引用 59 楼 的回复:

引用 57 楼 的回复:
楼主不知道能否提供的同步版的,就要同步的,不要异步的。
http://topic.csdn.net/u/20120713/17/2cfca3fe-a527-4c6c-a397-288629bccbce.html?seed=1733111358&r=79148395#r_79……


非常感谢,确实是如你所说的,可以实现。我去把我的贴结掉,给分。
另外,安装了你说的这个sdk后,还要引用个dll,%MyDocument%\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary_Phone.dll
否则没有GetResponseAsync这个方法。

下面是我对你第三个方法的一点小完善,也是我自己代码中用的方法
        public static async Task<string> ReqestAsync(string url)
        {
            HttpWebRequest request = HttpWebRequest.CreateHttp(url);
            request.Method = "GET";

HttpWebResponse webResponse = (HttpWebResponse)await request.GetResponseAsync();
string resultString = string.Empty;

using (Stream streamResult = webResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(streamResult))
{
resultString = await reader.ReadToEndAsync();
}
}
webResponse.Close();

            return resultString;
        }


最后,调用这个方法的方法也要用加 async ,否则会出错,例子:
		public async Task<bool> Update()
{
string link="http://www.baidu.com";

string html = await Helper.ReqestAsync(link);
return true;


--------------------编程问答-------------------- --------------------编程问答-------------------- 不错不错,mark --------------------编程问答-------------------- 好贴,先顶 --------------------编程问答-------------------- 好贴,顶个 --------------------编程问答-------------------- 大爱楼主 --------------------编程问答-------------------- 还有一种利用 RX 的,当然还是基于 Task 的 异步编程模型最直观,简洁。 --------------------编程问答-------------------- 谢谢LZ分享,LZ好人呐 --------------------编程问答-------------------- --------------------编程问答-------------------- 不错的东西 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 不错 不错  学习了 --------------------编程问答-------------------- 这么好的帖子 学习了· --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 很有用,收藏了!  --------------------编程问答-------------------- 更上一层楼啊 --------------------编程问答-------------------- 第三种await就是传说中windows 8的全新线程方式吧 --------------------编程问答-------------------- 标记、学习以及收藏。 感谢楼主分享。 --------------------编程问答-------------------- 如果需要下载的数据量很大的话,会不会出现多次回调的情况,那么像第二种方法会不会有问题????希望楼主解答. --------------------编程问答-------------------- 学习~楼主好人 --------------------编程问答--------------------
引用 84 楼  的回复:
如果需要下载的数据量很大的话,会不会出现多次回调的情况,那么像第二种方法会不会有问题????希望楼主解答.

几次回调只和几次请求有关。
数据量很大只会出现回调的响应时间很长的问题。 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 学习一下 --------------------编程问答-------------------- 每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分   --------------------编程问答-------------------- 受教,呵呵,收藏~~ --------------------编程问答-------------------- 楼主,你好,看了您的帖子很受启发的说,但是就第三种方式,我在我的环境下无法实现,HttpWebResponse webResponse = await request.GetResponseAsync();,其中request中没有GetResponseAsync这个方法,我是VS2012,wp8环境,不知道你们是怎么实现的,让UI线程等待HttpWebRequest取得数据,希望能够得到您的指点,万分感谢。 --------------------编程问答--------------------
引用 92 楼 zwt379716066 的回复:
楼主,你好,看了您的帖子很受启发的说,但是就第三种方式,我在我的环境下无法实现,HttpWebResponse webResponse = await request.GetResponseAsync();,其中request中没有GetResponseAsync这个方法,我是VS2012,wp8环境,不知道你们是怎么实现的,让UI线程等待HttpWebRequest取得……


你得安装async ctp --------------------编程问答-------------------- 第三种方式很好,不过楼主的代码是不是有问题

private async resultString Reqest()

async 后面必须要跟Task<T> 参数,结合你的上下文,这样写肯定通不过编译 --------------------编程问答-------------------- 正确的写法应该是
private async Task<string> Reqest()
--------------------编程问答--------------------
引用 94 楼 cacaca6 的回复:
第三种方式很好,不过楼主的代码是不是有问题

private async resultString Reqest()

async 后面必须要跟Task<T> 参数,结合你的上下文,这样写肯定通不过编译


你可以编译试一下:) --------------------编程问答-------------------- 为啥返回值为null呢? --------------------编程问答--------------------
引用 97 楼 zhangqiufang123 的回复:
为啥返回值为null呢?


哪里返回null --------------------编程问答--------------------
  public delegate void GetResultEventHandler(object sender, string e);
        public event GetResultEventHandler OnGetInfoCompleted;

        private void Reqest(string str)
        {
            System.Net.HttpWebRequest request = System.Net.HttpWebRequest.CreateHttp(str);
            request.Method = "GET";
            request.BeginGetResponse(GetInfoCompleted, request);

        }

        protected void GetInfoCompleted(IAsyncResult asyncResult)
        {
            try
            {
                System.Net.HttpWebRequest webRequest = asyncResult.AsyncState as System.Net.HttpWebRequest;
                System.Net.HttpWebResponse webResponse = (System.Net.HttpWebResponse)webRequest.EndGetResponse(asyncResult);
                System.IO.Stream streamResult = webResponse.GetResponseStream();
                System.IO.StreamReader reader = new System.IO.StreamReader(streamResult);

                //获取的返回值
                string resultString = reader.ReadToEnd();
                System.Windows.MessageBox.Show(resultString);
                if (OnGetInfoCompleted != null)
                {
                    
                    OnGetInfoCompleted(this, resultString);
                }
            }
            catch (System.Net.WebException ex)
            {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }

输出提示错误 --------------------编程问答--------------------
引用 99 楼 zhangqiufang123 的回复:
C# code?12345678910111213141516171819202122232425262728293031323334  public delegate void GetResultEventHandler(object sender, string e);        public event GetResultEventHandler OnGetIn……

楼主,为啥这个一输出就提示错误呢?
补充:移动开发 ,  Windows Phone
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,