跨线程有两种方法。
1:this.Dispatcher.BeginInvoke
2:SynchronizationContext
在上篇文章中我使用了第一种方法。显然每次都要调用this.Dispatcher.BeginInvoke是一件很“环照”的事情。
为了完善RestInvoke,我打算使用SynchronizationContext类,而SynchronizationContext类要和WebRequest关联。
为什么要和WebRequest关联呢?
因为一个Request对应了一个线程上下文,所以要保存请求时候的线程上下文,然后在成功获取数据后再调用保存的线程上下文来跨线程操作。
首先想到的是装饰模式,当然了,在这里可以用,但是从简单性角度考虑,就把Request和SynchronizationContext一起保存在HttpSyncWebRequest类中了。
///
<summary>
///
同步HttpWebRequest
///
</summary>
public
class
HttpSyncWebRequest
{
public
HttpWebRequest HttpWebRequest {
get
;
set
; }
public
SynchronizationContext SyncContext {
get
;
set
; }
}
代码很简单就是保存一个HttpWebRequest 和SyncContext对象。
在RestInvoke中,我们要修改GetWebRequest方法。代码如下:
///
<summary>
///
获取WebRequest对象
///
</summary>
///
<param name="requestUriString">
请求的地址
</param>
///
<param name="httpMethod">
请求的方法:GET,PUT,POST,DELETE
</param>
///
<param name="contentType">
请求的类型,json:"application/json"
</param>
///
<returns></returns>
public
static
HttpSyncWebRequest GetWebRequest(
string
requestUriString,
string
httpMethod,
string
contentType)
{
HttpWebRequest request
=
(HttpWebRequest)WebRequestCreator.ClientHttp.Create(
new
Uri(requestUriString));
request.Method
=
httpMethod;
if
(
!
string
.IsNullOrWhiteSpace(contentType))
{
request.ContentType
=
contentType;
}
return
new
HttpSyncWebRequest() { HttpWebRequest
=
request, SyncContext
=
SynchronizationContext.Current };
}
不是简单的返回HttpWebRequest对象,返回我们自定义的对象。
接着在每一个需要HttpWebRequest对象的地方使用
HttpSyncWebRequest syncWebRequest = GetWebRequest(requestUriString, httpMethod, "application/json;");
HttpWebRequest webRequest = syncWebRequest.HttpWebRequest;
例如
View Code
///
<summary>
///
调用GET方法
///
</summary>
///
<typeparam name="T">
结果的类型
</typeparam>
///
<param name="requestUriString">
请求的地址
</param>
///
<param name="action">
对结果的操作
</param>
public
static
void
InvokeGet
<
T
>
(
string
requestUriString, Action
<
T
>
action)
{
#region
添加时间戳,解决缓存问题
if
(requestUriString.IndexOf(
"
?
"
)
>
0
)
{
requestUriString
=
requestUriString
+
"
&
"
+
DateTime.Now.ToString();
}
else
{
requestUriString
=
requestUriString
+
"
?
"
+
DateTime.Now.ToString();
}
#endregion
HttpSyncWebRequest webRequest
=
GetWebRequest(requestUriString,
"
GET
"
,
string
.Empty);
webRequest.HttpWebRequest.BeginGetResponse((asyncResult)
=>
{
SynchronizationContext currentContext
=
asyncResult.AsyncState
as
SynchronizationContext;
WebResponse response
=
webRequest.HttpWebRequest.EndGetResponse(asyncResult);
HandleWebResponse(response, action,currentContext);
}, webRequest.SyncContext);
}
View Code
///
<summary>
///
同步处理WebResponse
///
</summary>
///
<typeparam name="T"></typeparam>
///
<param name="webResponse"></param>
///
<param name="action"></param>
///
<param name="currentContext"></param>
private
static
void
HandleWebResponse
<
T
>
(WebResponse webResponse, Action
<
T
>
action, SynchronizationContext currentContext)
{
using
(Stream responseStream
=
webResponse.GetResponseStream())
{
DataContractJsonSerializer serializer
=
new
DataContractJsonSerializer(
typeof
(T));
if
(
typeof
(T)
==
typeof
(
string
))
{
T responseObject
=
(T)(
object
)GetStringFromStream(responseStream);
currentContext.Post((callback)
=>
{
action(responseObject);
},
null
);
}
else
{
T responseObject
=
(T)serializer.ReadObject(responseStream);
currentContext.Post((callback)
=>
{
action(responseObject);
},
null
);
}
}
}