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

gnimgnot 2012-07-09 09:48:21
加精
为了不阻塞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线程保持通畅,并且代码的逻辑也能很清楚,又避开了线程同步的数据锁的麻烦。
算是在这件事情上现阶段较为完美的方案了。

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

顺便庆祝升星,炎热的夏天,散点分。
...全文
2907 114 打赏 收藏 转发到动态 举报
写回复
用AI写文章
114 条回复
切换为时间正序
请发表友善的回复…
发表回复
qieangel2013 2013-04-19
  • 打赏
  • 举报
回复
引用 112 楼 cuit 的回复:
引用 111 楼 zhangqiufang123 的回复:引用 110 楼 cuit 的回复:引用 108 楼 zhangqiufang123 的回复:引用 107 楼 cuit 的回复:引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复……
楼主,这个例子怎么用啊?请教楼主指教~
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 101 楼 cuit 的回复:
引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?12345678910111213141516171819202122232425262728293031323334 public delegate void GetResultEventHandler(object sender, str……

感谢楼主这么细心
错误提示

我在这个回调函数里输出什么都会提示这个错误,楼主,希望得到你的解答,先谢谢了~
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 100 楼 zhangqiufang123 的回复:
引用 99 楼 zhangqiufang123 的回复:C# code?12345678910111213141516171819202122232425262728293031323334 public delegate void GetResultEventHandler(object sender, string e); public event G……
什么错
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 99 楼 zhangqiufang123 的回复:
C# code?12345678910111213141516171819202122232425262728293031323334 public delegate void GetResultEventHandler(object sender, string e); public event GetResultEventHandler OnGetIn……
楼主,为啥这个一输出就提示错误呢?
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
  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);
            }
        }
输出提示错误
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 97 楼 zhangqiufang123 的回复:
为啥返回值为null呢?
哪里返回null
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
为啥返回值为null呢?
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 111 楼 zhangqiufang123 的回复:
引用 110 楼 cuit 的回复:引用 108 楼 zhangqiufang123 的回复:引用 107 楼 cuit 的回复:引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复……
if (OnGetInfoCompleted != null) { OnGetInfoCompleted(this, resultString); } 这个OnGetInfoCompleted就是自定义的事件。
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 110 楼 cuit 的回复:
引用 108 楼 zhangqiufang123 的回复:引用 107 楼 cuit 的回复:引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复……
楼主能不能给个把数据通过事件返回出去例子?
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 108 楼 zhangqiufang123 的回复:
引用 107 楼 cuit 的回复:引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复……
嗯。你可以把数据通过事件返回出去。
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 107 楼 cuit 的回复:
引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiuf……
就像这样操作
Me.Items.Add(New ItemViewModel() With {.LineOne = resultString, .LineTwo = "Dictumst eleifend facilisi faucibus", .LineThree = "Suscipit torquent ultrices vehicula volutpat maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus"})
我这个是wp8
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 107 楼 cuit 的回复:
引用 106 楼 zhangqiufang123 的回复:引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiuf……
楼主,这个我知道,我想把请求的数据resultstring来替换莫一个数据列表的值,可是一在上面操作就会提示错误,可能就是跨线程吧!我的意思就是想用请求的数据来输出列表
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 106 楼 zhangqiufang123 的回复:
引用 105 楼 cuit 的回复:引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?1234567891……
返回的值都在那个resultstring里
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 105 楼 cuit 的回复:
引用 104 楼 zhangqiufang123 的回复:引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?1234567891011121314151617181……
就是获取请求的数据?
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 104 楼 zhangqiufang123 的回复:
引用 103 楼 cuit 的回复:引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?123456789101112131415161718192021222324252627282930313233……
我不知道你说的返回值是啥。
qieangel2013 2013-04-18
  • 打赏
  • 举报
回复
引用 103 楼 cuit 的回复:
引用 102 楼 zhangqiufang123 的回复:引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?12345678910111213141516171819202122232425262728293031323334 public delegat……
哦!楼主我明白了,如果是这样,怎么才能获取返回值?
gnimgnot 2013-04-18
  • 打赏
  • 举报
回复
引用 102 楼 zhangqiufang123 的回复:
引用 101 楼 cuit 的回复:引用 100 楼 zhangqiufang123 的回复:引用 99 楼 zhangqiufang123 的回复:C# code?12345678910111213141516171819202122232425262728293031323334 public delegate void GetResultEventHandler(……
目测你跨线程执行了。 在非UI线程里操作UI,比如你这里要弹出对话框,需要用Dispacher.BeginInvoke().
gnimgnot 2013-04-15
  • 打赏
  • 举报
回复
引用 94 楼 cacaca6 的回复:
第三种方式很好,不过楼主的代码是不是有问题 private async resultString Reqest() async 后面必须要跟Task<T> 参数,结合你的上下文,这样写肯定通不过编译
你可以编译试一下:)
cacaca6 2013-04-15
  • 打赏
  • 举报
回复
正确的写法应该是 private async Task<string> Reqest()
cacaca6 2013-04-15
  • 打赏
  • 举报
回复
第三种方式很好,不过楼主的代码是不是有问题 private async resultString Reqest() async 后面必须要跟Task<T> 参数,结合你的上下文,这样写肯定通不过编译
加载更多回复(60)

7,655

社区成员

发帖
与我相关
我的任务
社区描述
Windows Phone是微软发布的一款手机操作系统,它将微软旗下的Xbox LIVE游戏、Zune音乐与独特的视频体验整合至手机中。
社区管理员
  • Windows客户端开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧