产生进行文件监控的临时线程的好方法?

时间:2013-06-06 00:33:53

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

我有以下情况,我不确定如何处理它。

在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包。

1 个答案:

答案 0 :(得分:2)

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);
}