首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在线程中编辑文件

在线程中编辑文件
EN

Stack Overflow用户
提问于 2010-10-23 06:28:23
回答 1查看 87关注 0票数 2

我目前正在研究一个xml服务,它是来自其他站点的服务的20+其他xml的总和。所以一开始它是公正的;

代码语言:javascript
复制
GetherDataAndCreateXML();

但显然,获取20+其他xml、编辑和服务它需要时间,所以我决定缓存它大约10分钟,并添加了一个带有DateTime属性的final.xml文件,以检查它是否过时等等。

代码语言:javascript
复制
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()函数。所以我就这么做了

代码语言:javascript
复制
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中添加了一个小属性,即“更新”;

代码语言:javascript
复制
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应用程序,我可以做得更好一些,但我认为这会改变许多事情,对吗?

EN

回答 1

Stack Overflow用户

发布于 2010-10-23 07:09:14

你有几个选择。

方法1

首先,您可以使用.NET的异步API来获取数据。假设您使用的是HttpWebRequest,那么您需要查看BeginGetResponseEndGetResponse,以及Stream上的BeginReadEndRead方法,然后返回响应。

示例

代码语言:javascript
复制
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

您的代码可能如下所示:

代码语言:javascript
复制
// 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();
}

希望这对你来说已经足够了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4002818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档