我目前正在开发一个 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 分钟以上 = 从缓存中返回
目前它有效并且看起来不错,但问题是;我对这类东西(xml 服务、线程、锁等)非常缺乏经验,所以我不确定它是否能在更艰难的情况下完美运行。例如,我的自定义锁定是否会在交通繁忙时产生问题,我是否应该切换到锁定文件等。
所以我正在寻找有关此过程的任何建议/更正,什么是“最佳实践”等。
提前致谢
完整代码:http://pastebin.com/UH94S8t6
同时为我的英语道歉,因为它不是我的母语,而且当我现在极度失眠/疲倦时,情况会变得更糟。
编辑:哦,我真的很抱歉,但不知何故我忘了提一件重要的事情;这一切都适用于 Asp.Net Mvc2。我认为如果它不是网络应用程序我可以做得更好一些,但我认为这会改变很多事情,对吗?
最佳答案
这里有几个选项。
方法#1
首先,您可以使用 .NET 的异步 API 来获取数据。假设您使用的是 HttpWebRequest
你想看看BeginGetResponse
和 EndGetResponse
,以及 BeginRead
和 EndRead
Stream
上的方法,您会得到响应。
例子
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();
}
希望这足以让您继续工作。
关于c# - 在线程中编辑文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4002818/