使用FileSystemWatcher时我应该有多个线程吗?

时间:2012-11-01 18:15:28

标签: c# filesystemwatcher

我有一个MVC3网络应用程序,用户可以通过该应用程序将文本文件上传到服务器上的APP Data / Upload文件夹。要求是通过FTP将这些新上传的文件传输到另一台服务器上的文件夹。我在控制台应用程序中使用了FileSystemWatcher来监视此Upload文件夹。完全创建文件后,我将这个新生成的文件传输到FTP文件夹。

我担心的是,如果多个实例/用户从Web应用程序上传文件,我的控制台应用程序将如何处理该方案?例如,我是否需要有一个队列并使用例如下面的FileProcesser处理不同线程上的文件?

public class FileProcessor
{
    private readonly Queue<string> files = new Queue<string>();
    private Thread thread;
    private readonly EventWaitHandle waitHandle = new AutoResetEvent(true);
    private static readonly object lockObject = new object();

    private volatile bool shouldStop = false;

    #region Helper methods

    private static bool IsFileUploadComplete(string path)
    {
        try
        {
            using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                return true;
            }
        }
        catch (IOException)
        {
            return false;
        }
    }

    private void ProcessFile(string path)
    {
        // Check if Result file has been completely created / uploaded
        int maximumProcessRetries = 5;
        int delayBeforeRetry = 5000; //in milliseconds, 5 seconds

        int attempts = 0;

        while (true)
        {
            if (IsFileUploadComplete(path))
            {
                //1. Open in existing IE process on Instrument Workstation
                var p = new System.Diagnostics.Process();
                var s = new System.Diagnostics.ProcessStartInfo(Settings1.Default.RSLSM_URL);
                s.UseShellExecute = true;
                s.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                p.StartInfo = s;
                p.Start();

                //2. Open in new IE process on Instrument workstation
                //System.Diagnostics.Process.Start("IEXPLORE.EXE", "www.yahoo.com");

                break;
            }
            attempts += 1;
            if (attempts >= maximumProcessRetries)
            {
                // Log error and send out notifications to RSLMS Database or Email RSLMS Admin group?
                break;
            }
            Thread.Sleep(delayBeforeRetry);
        }

        // Add any logic after the file has been processed
        //File.Delete(path);
    }

    private void Work()
    {
        while (!shouldStop)
        {
            string path = String.Empty;
            lock (lockObject)
            {
                if (files.Count > 0)
                {
                    path = files.Dequeue();
                }
            }

            if (!String.IsNullOrEmpty(path))
            {
                // Process the file
                ProcessFile(path);
            }
            else
            {
                // If no files are left to process then wait
                waitHandle.WaitOne();
            }
        }
    }

    #endregion

    #region Methods

    public void EnqueueFile(string path)
    {
        // Queue the file
        lock (lockObject)
        {
            files.Enqueue(path);
        }

        // Initialize and start the worker thread when the first file is queued
        // or when it has been stopped and thus terminated.
        if (thread == null || shouldStop)
        {
            thread = new Thread(new ThreadStart(Work));
            thread.Start();
        }
        // If the thread is waiting then start it
        else if (thread.ThreadState == ThreadState.WaitSleepJoin)
        {
            waitHandle.Set();
        }
    }

    public void StopProcessing()
    {
        shouldStop = true;
    }

    #endregion
}

1 个答案:

答案 0 :(得分:1)

您的FileSystemWatcher在其自己的线程上运行,并通知您的服务器代码已发生某些事情(在您的情况下创建了一个文件)。

如果args传递给您的代码,它会提供一个已创建的文件列表,您可以处理该文件列表。在您运行的进程中引发的任何事件都将在另一个线程上运行或排队,具体取决于您的锁定策略。

但是,一般情况下,当我收到一个事件时,我会从Directory.GetFiles获取所有文件的列表并处理该列表。它保证我不会丢失观察者事件中的任何文件。

如果要在生产中运行,您将需要摆脱该控制台应用程序并使您的进程作为Windows服务运行。控制台应用程序太脆弱了,任何走到该控制台的人都可以终止它。