如何在 Transform 上设置超时

How to put a timeout on Transform

XslCompiledTransform.Transform 在某些情况下(堆栈溢出、无限循环等)会挂起。这是一个依赖于数据(输入)的错误,所以我无法完全控制它的发生。如果发生这种情况,我希望得到优雅的通知,但我不希望它破坏我的应用程序进程以及用户输入输入的 GUI,这可能是 "valid" 但 "incomplete".

如果我 运行 手动 xslt 文件,我得到

Process is terminated due to WhosebugException

但是 XslCompiledTransform.Transform() 会挂起我的应用程序 永远

所以,我想在超时时结束该调用,但我尝试过的任何方法似乎都不起作用。它仍然挂起应用程序。

我希望有 try 块的线程不被挂起。我想创建两个任务,一个用于转换,另一个用于超时。然后同时启动两者。我不知道,但我认为 Run 在外部语句有机会连接超时并使用 WhenAny 之前 运行ning。

如何解决这个问题?

更新

我更新了代码以反映我当前的尝试。如果超时,我可以进入 if 块,但无论我是否中止线程,应用程序仍然挂起。我不明白 XslCompiledTransform.Transform 坚持在应用程序出现故障时将整个应用程序关闭是什么意思。

public static Object Load(string mathML)
{
  if (mathML == Notebooks.InputCell.EMPTY_MATH)
    return null;
  XmlDocument input = new XmlDocument();
  input.LoadXml(mathML);
  XmlDocument target = new XmlDocument(input.CreateNavigator().NameTable);
  using (XmlWriter writer = target.CreateNavigator().AppendChild())
  {
    try
    {
      Thread thread = null;
      var task = Task.Run(() => 
      {
        thread = Thread.CurrentThread;
        XmlTransform.Transform(input, writer);
      });
      if (!task.Wait(TimeSpan.FromSeconds(5)))
      {
        thread.Abort();
        throw new TimeoutException();
      }
    }
    catch (XsltException xex)
    {
      if (xex.Message == "An item of type 'Attribute' cannot be constructed within a node of type 'Root'.")
        return null;
      else
        throw;
    }
  }
  return Load(target);
}

这是我解决问题的方法

我将我的 xsl 编译成一个程序集,并从我的项目(称为 Library)中引用该程序集

优点:

  • 修复了挂起问题
  • 将 xslt 编译成程序集据说要快得多

缺点:

  • 你告诉我!我不知道:)

库属性/生成事件/预生成事件

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7 Tools\xsltc.exe" /settings:script+ /class:Transform "myStylesheet.xslt"

图书馆/参考文献

+ myStylesheet.dll

正在加载编译的转换

private static XslCompiledTransform xslTransform;
private static XslCompiledTransform XslTransform
{
  get
  {
    if (xslTransform == null)
    {
      xslTransform = new XslCompiledTransform();
      xslTransform.Load(typeof(Transform));
    }
    return xslTransform;
  }
}

调用转换

与问题中的更新代码相同