我有一个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
}
答案 0 :(得分:1)
您的FileSystemWatcher在其自己的线程上运行,并通知您的服务器代码已发生某些事情(在您的情况下创建了一个文件)。
如果args传递给您的代码,它会提供一个已创建的文件列表,您可以处理该文件列表。在您运行的进程中引发的任何事件都将在另一个线程上运行或排队,具体取决于您的锁定策略。
但是,一般情况下,当我收到一个事件时,我会从Directory.GetFiles获取所有文件的列表并处理该列表。它保证我不会丢失观察者事件中的任何文件。
如果要在生产中运行,您将需要摆脱该控制台应用程序并使您的进程作为Windows服务运行。控制台应用程序太脆弱了,任何走到该控制台的人都可以终止它。