我目前正在研究一个xml服务,它是来自其他站点的服务的20+其他xml的总和。所以一开始它是公正的;
GetherDataAndCreateXML();但显然,获取20+其他xml、编辑和服务它需要时间,所以我决定缓存它大约10分钟,并添加了一个带有DateTime属性的final.xml文件,以检查它是否过时等等。
var de = DateTime.Parse(x.Element("root").Attribute("DateTime").Value).AddSeconds(10.0d);
if (de >= DateTime.Now)
return finalXML();
else
{
RefreshFinalXml();
return finalXML();
}现在的问题是,在这10分钟之后的任何请求显然要花费太多的时间,因为它正在等待我的RefreshFinalXml()函数。所以我就这么做了
if (ndt >= DateTime.Now)
return finalXML();
else
{
ThreadStart start = RefreshFinalXml;
var thr = new Thread(start);
thr.IsBackground = true;
thr.Start();
return finalXML();
}这样,即使在第11分钟,我也只是返回旧的final.xml,但同时在后台启动另一个线程来刷新当前的xml。因此,在大约13分钟之后,用户可以毫不拖延地获得新的数据。但是这仍然存在一个问题:它为10到13分钟之间的每一个请求创建一个新线程(而第一个RefreshFinalXml仍然在后台工作),显然我不能让这种情况发生,对吗?而且,由于我对锁定文件和检测它是否是锁不太了解,所以我在最后的xml中添加了一个小属性,即“更新”;
if (ndt >= DateTime.Now)
return finalXML();
else
{
if (final.Element("root").Attribute("Updating").Value != "True")
{
final.Element("root").SetAttributeValue("Updating", "True");
final.Save(Path);
ThreadStart start = RefreshFinalXml;
//I change Updating Attribute back to False at the end of this function , right before saving Final Xml
var thr = new Thread(start);
thr.IsBackground = true;
thr.Start();
}
return finalXML();
}所以,0-10分钟=从缓存返回
10~13分钟=从缓存返回,而只有一个线程正在刷新final.xml 13+ 13+=从缓存返回
它目前还不错,但问题/问题是,我对这类东西( xml服务、线程、锁等)非常缺乏经验,所以我不确定它在更困难的情况下是否能完美地工作。例如,如果我切换到锁定文件等,我的自定义锁定会在流量大的情况下造成问题吗?
因此,我正在寻找任何关于这个过程的建议/纠正,什么是“最佳实践”等等。
提前感谢
完整代码:http://pastebin.com/UH94S8t6
同时也为我的英语道歉,因为它不是我的母语,而且当我现在极度失眠/疲惫不堪时,情况会变得更糟。
编辑:哦,我真的很抱歉,但不知怎么的,我忘了提到一件关键的事情;这一切都是关于Asp.Net Mvc2的。我认为如果不是一个web应用程序,我可以做得更好一些,但我认为这会改变许多事情,对吗?
发布于 2010-10-23 07:09:14
你有几个选择。
方法1
首先,您可以使用.NET的异步API来获取数据。假设您使用的是HttpWebRequest,那么您需要查看BeginGetResponse和EndGetResponse,以及Stream上的BeginRead和EndRead方法,然后返回响应。
示例
var request = WebRequest.Create("http://someurl.com");
request.BeginGetResponse(delegate (IAsyncResult ar)
{
Stream responseStream = request.EndGetResponse(ar).GetResponseStream();
// use async methods on the stream to process the data -- omitted for brevity
});方法2
另一种方法是使用线程池来完成您的工作,而不是创建和管理您自己的线程。这将有效地限制正在运行的线程的数量,并消除在创建新线程时通常会受到的性能影响。
现在,你不想在等待的时候重复触发更新,这是对的。
例2
您的代码可能如下所示:
// We use a dictionary here for efficiency
var Updating = new Dictionary()<TheXMLObjectType, object>;
...
if (de >= DateTime.Now)
{
return finalXML();
}
else
{
// Lock the updating dictionary to prevent other threads from
// updating it before we're done.
lock (Updating)
{
// If the xml is already in the updating dictionary, it's being
// updated elsewhere, so we don't need to do anything.
// On the other hand, if it's not already being updated we need
// to queue RefreshFinalXml, and set the updating flag
if (!Updating.ContainsKey(xml))
{
// Use the thread pool for the work, rather than managing our own
ThreadPool.QueueUserWorkItem(delegate (Object o)
{
RefreshFinalXml();
lock(Updating)
{
Updating.Remove(xml);
}
});
// Set the xml in the updating dictionary
Updating[xml] = null;
}
}
return finalXML();
}希望这对你来说已经足够了。
https://stackoverflow.com/questions/4002818
复制相似问题