未报告RunWorkerCompleted异常

时间:2012-07-17 10:20:56

标签: c# multithreading exception-handling backgroundworker file-handling

背景:

我正在处理一个处理'信号量'文件的服务。这些是放置在单个目录中的txt文件,其中包含需要读入数据库的xml文件的链接。有一个以前的版本,但它不小心数据丢失所以我的新服务在任何情况下都非常小心处理文件。

具体细节:

我有一个BackgroundWorker池,用于a)将新文件复制到'Processing'文件夹(因为它在unix机器上,因此copy会更改文件权限以便我可以使用它)并将其添加到队列和b)处理文件内容。

我不想保持文件打开,因此SemaphoreFile类包含对其位置的引用,并管理文件的读取和写入。它甚至可以在析构函数中处理文件清理,这样即使是可怕的崩溃也应该保留数据。

预期:

在处理文件的RunWorkerCompleted方法中,我希望返回semaphoreFile,以便我可以调用dispose方法。如果all都成功,则文件将被删除,semaphoreFile实例将保留范围。如果进程出错,在许多情况下它应该执行,那么我处理错误,将文件标记为有问题(它将错误写入该数据下的文件并将其移动到新的'Prolematic'文件夹)并再次处理()。

我添加了throw new NotImplementedException(“No error or results”);因为我需要确保它永远不会被击中,所以我可以在我的调试器中查找它。我需要一个对信号量文件的引用,以便整理它。如果我不能这样做那么它就会丢失。

问题:

当前问题是后台工作程序运行'GetResult',它会执行错误,但e.Error为null。这意味着e.Result也是null并且我遇到了这个我从未想过的错误。

为什么在SemaphoreFile.GetResults中有异常时e.Error为null?

Code Snippits

执行:

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

RunWorkerCompleted:

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

SemaphoreFile.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;
}

非常感谢你的时间^ _ ^

0 个答案:

没有答案