跨线程有两种方法。
1:this.Dispatcher.BeginInvoke
2:SynchronizationContext
在上篇文章中我使用了第一种方法。显然每次都要调用this.Dispatcher.BeginInvoke是一件很“环照”的事情。
为了完善RestInvoke,我打算使用SynchronizationContext类,而SynchronizationContext类要和WebRequest关联。
为什么要和WebRequest关联呢?
因为一个Request对应了一个线程上下文,所以要保存请求时候的线程上下文,然后在成功获取数据后再调用保存的线程上下文来跨线程操作。
首先想到的是装饰模式,当然了,在这里可以用,但是从简单性角度考虑,就把Request和SynchronizationContext一起保存在HttpSyncWebRequest类中了。
/// 同步HttpWebRequest
/// </summary>
public class HttpSyncWebRequest
{
public HttpWebRequest HttpWebRequest { get ; set ; }
public SynchronizationContext SyncContext { get ; set ; }
}
代码很简单就是保存一个HttpWebRequest 和SyncContext对象。
在RestInvoke中,我们要修改GetWebRequest方法。代码如下:
/// 获取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;
例如
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// 调用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);
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// 同步处理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 );
}
}
}