1

背景:

我正在开发一项处理“信号量”文件的服务。这些是放置在单个目录中的 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;
}

非常感谢您的宝贵时间^_^

4

0 回答 0