【问题标题】:Good way to spawn a temporary thread that does file monitoring?生成执行文件监视的临时线程的好方法?
【发布时间】:2013-06-07 06:14:14
【问题描述】:

我有以下情况,我不确定如何最好地处理。

在 ASP.NET MVC 4 系统上,我有一个控制器操作,它调用外部系统(在同一网络中),在 1 到 10 分钟内,该系统将生成 3 个 XML 文件并将它们放在一个文件夹中托管 ASP.NET MVC 应用程序的同一台服务器。

起初我想使用带有 FileSystemWatcher 的 Windows 服务来监视文件夹中的 XML 文件,但有人要求我提出一个替代解决方案,以防安装 Windows 服务不可行。

我只做了很少的线程,所以我不确定执行此操作的理想方法是什么。

理论上,控制器操作将调用外部系统(这是一个 Web 服务 (asmx) 调用),然后,我想触发一个短期线程,该线程将执行长达 10 分钟,如果找到 .文件夹中的xml文件,它会处理它们。

谢谢

-- 编辑、更新

Brandon 的解决方案完全符合我的需要,但他说要从另一个 stackoverflow 问题中获取 Task.Delay 方法代码,从反编译 Async 库的人那里获取。这对我不起作用,所以我必须获取 Microsoft.CompilerServices.AsyncTargetingPack NuGet 包。

【问题讨论】:

  • Windows 服务绝对是处理此问题的更好方法。但如果你真的需要在 ASP.NET 中使用它,Phil Haack has a good blog post 了解如何对其进行陪审。
  • @StephenCleary,我同意,唯一的问题是拥有 Windows 服务(我们已经拥有,如果可以的话,我们只是想将其排除在外)是另一个额外的故障点,一些其他配置,为其获取安装程序等。Brandon 的解决方案非常适合我们的需要。
  • 你读过我链接的博文吗? “完美运行”不是我会使用的术语……“极其危险”更适合 IMO。
  • 我确实读过斯蒂芬,它不是 100% 安全的,但我会说它是 99%,至少在我的场景中。我认为 Phil 是一位出色的开发人员,如果他开发并正在使用这个东西(并且还为涉及 ASP.NET 内部的开发人员提供了建议),我会说使用它足够安全,不是吗?
  • Phil 撰写该博文时,他是 ASP.NET MVC 框架的高级程序经理。因此,如果他使用诸如“危险”、“狂野”、“邪恶”和“不受支持”之类的术语,那么我会以适当的恐惧来接近解决方案。

标签: c# asp.net-mvc multithreading asp.net-mvc-4


【解决方案1】:

FileSystemWatcher 不需要线程或 Windows 服务。只需创建它,设置您的事件处理程序,然后将 EnableRaisingEvents 设置为 true。然后启动一个在 10 分钟后到期的计时器并处理观察者。比如:

private async void RunAfterDelay(TimeSpan delay, CancellationToken token, Action action)
{
    await Task.Delay(delay, token);
    if (!token.IsCancellationRequested)
    {
        action();
    }
}

private void RunWatcher()
{

    var cts = new CancellationTokenSource();
    var watcher = new FileSystemWatcher();
    watcher.Path = "...";
    watcher.Created += (_, e) =>
    {
        if (e.FullPath == "file-you-are-interested-in")
        {
           // cancel the timer
           cts.Cancel();

           // do your stuff
           // ...

           // get rid of the watcher
           watcher.Dispose();
        }
    };

    watcher.EnableRaisingEvents = true;

    // start the timer
    RunAfterDelay(TimeSpan.FromMinutes(10), cts.Token, () =>
    {
        // get rid of the watcher
        watcher.Dispose();

        // do anything else you want to do, like send out failure notices.
    });
}

这将开始监听观察者,如果你得到你想要的,它会处理观察者。如果计时器到期,它将停止观察者。

以上是针对 .NET 4.5。如果您的目标是 4.0,则首先获取此处显示的 Delay 的实现:https://stackoverflow.com/a/9068520/674326

然后把RunAfterDelay改成这样:

private void RunAfterDelay(TimeSpan delay, CancellationToken token, Action action)
{
    TaskEx.Delay(delay, token).ContinueWith(t => action(), TaskContinuationOptions.OnlyOnRanToCompletion);
}

【讨论】:

  • 嗨@Brandon。我使用的是 .NET 4.0,而不是 4.5,所以我认为 async 和 await 不可用。是否可以将代码调整为不使用异步等待?
  • MVC 4 是为 .NET 4.5 设计的。也许您在 .NET 4 上使用 MVC 3?
  • 不,Stephen,我的目标是 ASP.NET MVC 4 上的 .NET 4.0。试试看 :)
  • @GR7 - 我在底部添加了一些位来建议 .NET 4.0 的更改。
  • 非常感谢布兰登的帮助。让我快速尝试一下,如果可行,我会标记为答案:)
猜你喜欢
  • 2016-07-14
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多