C#异步方法还挂着UI [英] C# async methods still hang UI
问题描述
我有这两种方法,我想异步运行,以保持UI响应。但是,它仍然挂在UI。有什么建议?
异步无效DoScrape()
{
VAR饲料=新饲料(); VAR的结果=等待feed.GetList();
的foreach(在结果VAR itemObject)
{
VAR项目=新的ListViewItem(itemObject.Title);
item.SubItems.Add(itemObject.Link);
item.SubItems.Add(itemObject.Description);
LstResults.Items.Add(项目);
}
}
公共类饲料
{
异步公共任务<名单,LT; ItemObject>>的GetList()
{
VAR的客户=新的WebClient();
字符串内容=等待client.DownloadStringTaskAsync(新的URI(anyUrl));
VAR lstItemObjects =新的List< ItemObject>();
VAR饲料=新的XmlDocument();
feed.LoadXml(内容);
VAR节点= feed.GetElementsByTagName(项目); 的foreach(在节点XmlNode的节点)
{
VAR tmpItemObject =新ItemObject();
VAR标题=节点[标题];
如果(标题!= NULL)tmpItemObject.Title = title.InnerText;
VAR链接=节点[链接];
如果(链接!= NULL)tmpItemObject.Link = link.InnerText;
Var描述=节点[说明];
如果(说明!= NULL)tmpItemObject.Description = description.InnerText;
lstItemObjects.Add(tmpItemObject);
}
返回lstItemObjects;
}
}
我怀疑 DownloadStringTaskAsync
依赖<一个href=\"http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx\"><$c$c>HttpWebRequest.BeginGetResponse$c$c>在一个较低的水平。既然如此,它已知为一的WebRequest设置不完全异步的。烦人(坦白地说,愚蠢)是同步执行异步的WebRequest的DNS查找阶段,因此块。我怀疑这可能是你所观察的问题。
在文档警告:
块引用>您已经两个选择:
- 启动从一个工作线程的请求(高负荷下运行的线程池饥饿的风险,由于阻止行为)
- (云林)执行之前发射要求的纲领性DNS查找。这能被异步完成。希望请求将然后使用缓存DNS查找。
我们去了3号(和昂贵的)实现我们自己的正常异步HTTP库获得体面的吞吐量选项,但它可能是你的情况有点极端;)
I have these two methods, that I want to run async to keep the UI responsive. However, it's still hanging the UI. Any suggestions?
async void DoScrape() { var feed = new Feed(); var results = await feed.GetList(); foreach (var itemObject in results) { var item = new ListViewItem(itemObject.Title); item.SubItems.Add(itemObject.Link); item.SubItems.Add(itemObject.Description); LstResults.Items.Add(item); } } public class Feed { async public Task<List<ItemObject>> GetList() { var client = new WebClient(); string content = await client.DownloadStringTaskAsync(new Uri("anyUrl")); var lstItemObjects = new List<ItemObject>(); var feed = new XmlDocument(); feed.LoadXml(content); var nodes = feed.GetElementsByTagName("item"); foreach (XmlNode node in nodes) { var tmpItemObject = new ItemObject(); var title = node["title"]; if (title != null) tmpItemObject.Title = title.InnerText; var link = node["link"]; if (link != null) tmpItemObject.Link = link.InnerText; var description = node["description"]; if (description != null) tmpItemObject.Description = description.InnerText; lstItemObjects.Add(tmpItemObject); } return lstItemObjects; } }
解决方案I suspect
DownloadStringTaskAsync
relies uponHttpWebRequest.BeginGetResponse
at a lower level. This being the case, it is known that the setup for a webrequest is not fully asynchronous. Annoyingly (and frankly, stupidly) the DNS lookup phase of an asynchronous WebRequest is performed synchronously, and therefore blocks. I suspect this might be the issue you are observing.Reproduced below is a warning in the docs:
You've two choices:
- Start the request from a worker thread (and under high load, run the risk of ThreadPool starvation due to blocking behaviour)
- (Tenuously) Perform a programmatic DNS lookup prior to firing the request. This can be done asynchronously. Hopefully the request will then use the cached DNS lookup.
We went for the 3rd (and costly) option of implementing our own properly asynchronous HTTP library to get decent throughput, but it's probably a bit extreme in your case ;)
这篇关于C#异步方法还挂着UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!