您的位置:首页 > 编程语言 > ASP

asp.net mvc 特性 使用异步Controllers

2011-03-07 23:49 375 查看

使用asp.net异步执行请求的原因和好处,可以搜之,不赘叙。

看一个同步抓取网页图片的方法:

Public ContentResult GetPhotoByTag(string tag)

{

// Make a request to Flickr

string url = string.Format(FlickrSearchApi, HttpUtility.UrlEncode(tag));

using (var response = WebRequest.Create(url).GetResponse())

{

// Parse the response as XML

Var xmlDoc = XDocument.Load(XmlReader.Create(response.GetResponseStream()));

// Use LINQ to convert each <photo /> node to a URL string

var photoUrls = from photoNode in xmlDoc.Descendants("photo")

select string.Format(

"http://farm{0}.static.flickr.com/{1}/{2}_{3}.jpg",

photoNode.Attribute("farm").Value,

photoNode.Attribute("server").Value,

photoNode.Attribute("id").Value,

photoNode.Attribute("secret").Value);

// Return an <img> tag referencing the first photo

return Content(string.Format("<img src='{0}'/>", photoUrls.First()));

}

}

改写成异步。

实现异步Controller 3个关键点:

1,继承自AsyncController

2,方法名称格式:ActionNameAsync, ActionNameCompleted。

3,设置信号量

public class ImageController : AsyncController

{

public void GetPhotoByTagAsync(string tag)

{

AsyncManager.OutstandingOperations.Increment();

// Begin an asynchronous request to Flickr

string url = string.Format(FlickrSearchApi, HttpUtility.UrlEncode(tag));

WebRequest request = WebRequest.Create(url);

request.BeginGetResponse(asyncResult =>

{

// This lambda method will be executed when we've got a response from Flickr

using (WebResponse response = request.EndGetResponse(asyncResult))

{

// Parse response as XML, then convert to each <photo> node to a URL

var xml = XDocument.Load(XmlReader.Create(response.GetResponseStream()));

var photoUrls = from photoNode in xml.Descendants("photo")

select string.Format(

"http://farm{0}.static.flickr.com/{1}/{2}_{3}.jpg",

photoNode.Attribute("farm").Value,

photoNode.Attribute("server").Value,

photoNode.Attribute("id").Value,

photoNode.Attribute("secret").Value);

AsyncManager.Parameters["photoUrls"] = photoUrls;

// Now allow the Completed method to run

AsyncManager.OutstandingOperations.Decrement();

}

}, null);

}

public ContentResult GetPhotoByTagCompleted(IEnumerable<string> photoUrls)

{

return Content(string.Format("<img src='{0}'/>", photoUrls.First()));

}

}

使用异步三部曲:1,方法名称:XXXXXAsync,XXXXXCompleted;2,一步方法中通过信号量控制同步:逻辑开始前递增信号量AsyncManager.OutstandingOperations.Increment();逻辑后递减信号量 AsyncManager.OutstandingOperations.Decrement();3,传参数和执行结果: AsyncManager.Parameters["photoUrls"] = photoUrls;

如何给completed传参数:

public void GetPhotoByTagAsync(string tag, string someOtherParam)

{

AsyncManager.Parameters["someOtherParam"] = someOtherParam;

// ... all else as before ...

}

public ContentResult GetPhotoByTagCompleted(IEnumerable<string> photoUrls,

string someOtherParam)

{

// ...

}

通过AsyncManager.Parameters集合传键值对参数,Completed方法会试图通过参数名称去匹配参数值。

如何指定超时:

[AsyncTimeout(10000)] // 10000 milliseconds equals 10 seconds

public void GetPhotoByTagAsync(string tag) { ... }

如何终止异步操作。

这里提供的方法比较粗暴,只能用AsyncManager.Finish()把所有未完成异步调用终止。该方法导致Completed提早调用,AsyncManager.Parameters里面的值会设置为默认值(0,null..etc)。

使用Sync() 强制回调方法运行在绑定了原始 HTTPContext的asp.net工作线程上:

在control中,假如异步方法带有回调,那么该回调将不可预见在什么线程上执行。自然不能肯定的去访问HTTPContext。解决办法是使用AsyncManager.Sync。示例:

BeginAsyncOperation (asyncResult => {

var result = End (asyncResult);

// Can't always access System.Web.HttpContext.Current from here...

Action doSomethingWithHttpContext = () => {

// ... but can always access it from this delegate

};

if (asyncResult.CompletedSynchronously) // Already on an ASP.NET thread

doSomethingWithHttpContext();

else // Must switch to an ASP.NET thread

AsyncManager.Sync(doSomethingWithHttpContext);

AsyncManager.OutstandingOperations.Decrement();

}, null);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: