背景:
我正在开发一项处理“信号量”文件的服务。这些是放置在单个目录中的 txt 文件,其中包含需要读入数据库的 xml 文件的链接。有一个以前的版本,但它对数据丢失很粗心,所以我的新服务在任何情况下都非常小心地处理文件。
规格:
我有一个 BackgroundWorker 池,用于 a) 将找到的新文件复制到“处理”文件夹(因为它在 unix 机器上,所以复制更改文件权限以便我可以使用它)并将其添加到队列和 b ) 处理文件内容。
我不想让文件保持打开状态,因此 SemaphoreFile 类包含对其位置的引用并管理文件的读取和写入。它甚至在其析构函数中处理文件清理,因此即使是可怕的崩溃也应该保留数据。
预期的:
在处理文件时的 RunWorkerCompleted 方法中,我希望返回 semaphoreFile 以便我可以调用 dispose 方法。如果一切成功,则文件将被删除并且 semaphoreFile 实例离开范围。如果进程出错(在许多情况下应该这样做),那么我处理错误,将文件标记为有问题(它将错误写入该数据下的文件并将其移动到新的“Prolematic”文件夹),然后再次处理()。
我添加了 throw new NotImplementedException("No error or results"); 因为我需要确保它永远不会被击中,所以我可以在我的调试器中查找它。我需要参考信号量文件以便整理它。如果我不能做到这一点,那么它将丢失。
问题:
当前的问题是后台工作人员运行'GetResult',它会出错,但e.Error为null。这意味着 e.Result 也是空的,我遇到了这个我从来不想看到的错误。
SemaphoreFile.GetResults 中出现异常时,为什么 e.Error 为 null?
代码片段
执行:
public static void Execute()
{
while (_isActive)
{
SemaphoreFile semaphoreFile;
lock (ThreadLock)
{
int threadIndex;
bool hasFreeThread = TryGetFreeThread(out threadIndex);
bool hasSemaphore = SemaphoreQueue.HasNext;
if (hasFreeThread && hasSemaphore)
{
semaphoreFile = SemaphoreQueue.Next;
_threads[threadIndex].DoWork += delegate(object sender, DoWorkEventArgs args)
{
try
{
BackgroundWorker bw = (BackgroundWorker)sender;
if (bw.CancellationPending)
args.Cancel = true;
args.Result = semaphoreFile.GetResults(bw);
if (bw.CancellationPending)
args.Cancel = true;
}
catch (Exception e)
{
Writelog.Write("An error occured processing file " + semaphoreFile + ":" + e.Message);
Writelog.WriteException(e);
}
}
;
_threads[threadIndex].RunWorkerCompleted += ThreadRunWorkerCompleted;
Debug.Print("Starting Thread @ index " + threadIndex);
_threads[threadIndex].RunWorkerAsync();
}
}
}
}
RunWorker 已完成:
private static void ThreadRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
if (e.Error.GetType() == typeof(SemaphoreFileException))
{
SemaphoreFileException semaphoreFileException = (SemaphoreFileException)e.Error;
semaphoreFileException.SemaphoreFile.MarkAsProblematic(e.Error);
semaphoreFileException.SemaphoreFile.Dispose();
}
else
{
if (!(e.Error.GetType() == typeof(SemaphoreResultFileException)))
{
throw e.Error;
}
SemaphoreResultFileException semaphoreResultFileException = (SemaphoreResultFileException)e.Error;
semaphoreResultFileException.SemaphoreFile.MarkAsProblematic(e.Error);
semaphoreResultFileException.SemaphoreFile.Dispose();
}
}
else
{
if (!e.Cancelled)
{
if (e.Result == null)
{
throw new NotImplementedException("No error or results");
}
if (e.Result.GetType() == typeof(SemaphoreFile))
{
SemaphoreFile semaphoreFile = (SemaphoreFile)e.Result;
semaphoreFile.Dispose();
}
}
}
}
信号量文件.GetResults
public SemaphoreFile GetResults(BackgroundWorker backgroundWorker)
{
if (!File.Exists(_fileInfo.FullName))
throw new SemaphoreFileException(this, string.Format("Semaphore {0} is missing", _fileInfo.FullName));
if (!Parse())
throw new SemaphoreFileException(this, string.Format("Semaphore {0} failed to parse correctly.", _fileInfo.FullName));
if (!_resultFiles.Any())
throw new SemaphoreFileException(this, string.Format("Semaphore {0} contains no Results.", _fileInfo.FullName));
List<Exception> resultFileExceptions = new List<Exception>();
foreach (ResultFile resultFile in _resultFiles)
{
if (backgroundWorker.CancellationPending)
{
IsFinished = false;
return this;
}
try
{
resultFile.Process();
string line = resultFile.ToString();
if (_lines.Contains(resultFile.ToString()))
{
_lines.Remove(line);
if (!_lines.Contains("Lines done in last run:"))
{
_lines.Add("Run @ " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
_lines.Add("Lines done in last run:");
}
_lines.Add(resultFile.ToString());
}
}
catch (Exception exception)
{
resultFileExceptions.Add(exception);
}
}
if (resultFileExceptions.Count > 0)
{
_fileInfo = MoveFile(SemaphoreSubFoldersEnum.Problematic);
throw new SemaphoreResultFileException(this, resultFileExceptions, string.Format("Results in Semaphore {0} contained errors:", _fileInfo.FullName));
}
return this;
}
非常感谢您的宝贵时间^_^