【发布时间】:2012-07-10 06:42:27
【问题描述】:
基本上我想实现简单的搜索功能,每当用户在视图中的文本框中输入一些关键字并单击提交按钮时,我想使用 TPL 异步机制对预定义的网站 URL 进行 ASYNC 调用。当我对控制台应用程序执行相同操作时,它就像一个魅力,但不适用于 ASP.NET MVC3。
找不到原因
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
[HttpPost]
public ActionResult Index(string text)
{
string[] url = { "http://www.msnbc.com", "http://www.yahoo.com",
"http://www.nytimes.com", "http://www.washingtonpost.com",
"http://www.latimes.com", "http://www.newsday.com" };
Task<string[]> webTask = this.GetWordCounts(url, text);
string[] results = null;
try
{
results = webTask.Result;
}
catch (AggregateException e)
{
}
return View("Index", results);
}
//Taken from MSDN
Task<string[]> GetWordCounts(string[] urls, string name)
{
TaskCompletionSource<string[]> tcs = new TaskCompletionSource<string[]>();
WebClient[] webClients = new WebClient[urls.Length];
object m_lock = new object();
int count = 0;
List<string> results = new List<string>();
for (int i = 0; i < urls.Length; i++)
{
webClients[i] = new WebClient();
#region callback
// Specify the callback for the DownloadStringCompleted
// event that will be raised by this WebClient instance.
webClients[i].DownloadStringCompleted += (obj, args) =>
{
if (args.Cancelled == true)
{
tcs.TrySetCanceled();
return;
}
else if (args.Error != null)
{
// Pass through to the underlying Task
// any exceptions thrown by the WebClient
// during the asynchronous operation.
tcs.TrySetException(args.Error);
return;
}
else
{
// Split the string into an array of words,
// then count the number of elements that match
// the search term.
string[] words = null;
words = args.Result.Split(' ');
string NAME = name.ToUpper();
int nameCount = (from word in words.AsParallel()
where word.ToUpper().Contains(NAME)
select word)
.Count();
// Associate the results with the url, and add new string to the array that
// the underlying Task object will return in its Result property.
results.Add(String.Format("{0} has {1} instances of {2}", args.UserState, nameCount, name));
}
// If this is the last async operation to complete,
// then set the Result property on the underlying Task.
lock (m_lock)
{
count++;
if (count == urls.Length)
{
tcs.TrySetResult(results.ToArray());
}
}
};
#endregion
// Call DownloadStringAsync for each URL.
Uri address = null;
try
{
address = new Uri(urls[i]);
// Pass the address, and also use it for the userToken
// to identify the page when the delegate is invoked.
webClients[i].DownloadStringAsync(address, address);
}
catch (UriFormatException ex)
{
// Abandon the entire operation if one url is malformed.
// Other actions are possible here.
tcs.TrySetException(ex);
return tcs.Task;
}
}
// Return the underlying Task. The client code
// waits on the Result property, and handles exceptions
// in the try-catch block there.
return tcs.Task;
}
这是我的观点 - 现在我将关键字硬编码为 microsoft
@using (Html.BeginForm("Index", "Home", new { text = "Microsoft" }))
{
<input type="submit" />
}
更新:它永远存在于 Index Post 方法的 try 块中
【问题讨论】:
-
抱歉没有提到这个问题。基本上当我尝试在这一行收获结果时 results = webTask.Result;在 Index 的 post 方法中,它永远留在那里
-
我认为这是我需要使用 AsyncController 的地方。我说的对吗?
-
是的,你是对的。这是 AsyncController 的绝佳候选者。
-
我对描述有点困惑 - 浏览器中的某些内容是否异步(ajax-y 样式/不是完整页面加载)与服务器端请求的处理方式(异步或同步,线/套接字级别的行为在任何一种情况下都将基本相同,因为我们不是在谈论 WebSockets 等)。我错过了什么吗?如果没有,您可能只想将其设为常规同步控制器/方法(无 TPL),然后看看效果如何。 FWIW,asp.net 同步上下文可能是挂起的原因,所以 ConfigureAwait(false);应该做的伎俩。
-
基本上我正在尝试在服务器端使用 TPL Async 在按钮单击时进行异步 Web 请求调用。
标签: asp.net asp.net-mvc-3 task-parallel-library