如何阻止“黑匣子”操作?

时间:2011-02-11 00:57:57

标签: c# .net xml xpath

我正在使用一个异步委托来调用一个将xml文件加载到XPathDocument中的方法。如果xml太大而无法放入内存中,则永远不会完成加载。如果xml文件成功加载到XPathDocument中,则下面的代码可以正常工作。我已经能够使用一个执行asyncXpath.EndInvoke(result)语句的计时器事件,它可以结束CreateDocument方法,但它不会阻止加载XPathDocument。我的结论是,我唯一能做的就是发出一个Application.End语句来杀死应用程序。有谁知道如何停止黑盒操作,如加载XPathDocument。

delegate bool AsyncXpathQueryCaller(string xmlfile 

bool found = false; 
AsyncXpathQueryCaller asyncXpath = new 
AsyncXpathQueryCaller(CreateDocument); 
IAsyncResult result = asyncXpath.BeginInvoke(xmlfile, null, null); 
while (!result.IsCompleted) 
{ 
result.AsyncWaitHandle.WaitOne(100, false); 

} 
found = asyncXpath.EndInvoke(result);


private bool CreateDocument (string xmlfile)
{
XPathDocument doc = new XPathDocument(xmlfile);
}

4 个答案:

答案 0 :(得分:1)

在尝试加载FileInfo并检查大小之前,如何使用它?如果它太大就跳过它。

这样的事情:

FileInfo fi = new FileInfo(xmlfile);
if(fi.Length < /*some huge number*/)
{
  //load the file
}

答案 1 :(得分:0)

您可以声明一个FileStream并将其提供给构造函数,但在此之前,请查看其Length属性,如果它太长,则只返回错误。

答案 2 :(得分:0)

编辑:我刚刚意识到KeithS已接近一个好的答案。基本的想法是,您调用接受Stream FileStream的{​​{3}}来包裹Read(byte[], int, int)。传递它的对象应该实现FileStream函数来调用包装的Read的{​​{1}}函数,或者如果操作超时则抛出异常。这是一个代码示例:

class XmlStream : FileStream
{
    DateTime deadline;

    public XmlStream(string filename, TimeSpan timeout)
           : base(filename, FileMode.Open)
    {
        deadline = DateTime.UtcNow + timeout;
    }

    public override int Read(byte[] array, int offset, int count)
    {
        if (DateTime.UtcNow > deadline)
            throw new TimeoutException();
        return base.Read(array, offset, count);
    }
}

这里有一些代码在document中读取,但在1秒后超时:

    bool found = true;
    using(var stream = new XmlStream(document, TimeSpan.FromSeconds(1)))
    try
    {
        xpath = new XPathDocument(stream);
    }
    catch (TimeoutException)
    {
        found = false;
    }

如果你创建一个单独的线程而不是BeginInvoke,你可以在计时器滴答时(或者有人点击“取消”)中止线程。虽然中止线程通常是不可取的,因为它可能持有锁或使全局数据处于不一致状态,在这种情况下它应该没问题,因为你的线程不会持有锁或访问全局数据。

此方法的代码与上一个示例的代码相同:

    bool found = false;
    thread = new Thread(() =>
    {
        xpath = new XPathDocument(document);
        found = true;
    });
    thread.Start();
    thread.Join(TimeSpan.FromSeconds(1));
    thread.Abort();

如果您对自己的应用域中的线程中止感到不舒服,可以在另一个应用域中创建该文档,如果花费的时间太长,则可以在其上调用AppDomain.Unload。这将需要一些编组,但可能不会有太多的开销。

能够终止进程的最终方法是在单独的进程中运行它并使用某种远程处理接口来访问它。但是,这可能比其他选项更麻烦,因为你不得不担心找到可执行文件,传递参数,一些用户终止它,等等。

答案 3 :(得分:0)

正如Abe Miessler所提议的那样,在尝试将文件大小加载到XPathDocument之前检查文件大小是明智的。

如何确定应该限制的内容

没有确切的规则,但我听说有人说你应该将文件大小乘以5,然后结果接近XmlDocument为了加载/解析文本而需要的内存。< / p>