Windows应用程序线程中止问题

时间:2010-12-20 20:41:37

标签: multithreading excel-interop

我正在开发一个应用程序,它必须根据文件监视器正在监视的文件夹中的文件做出具体决定。

此决策制定过程的一部分涉及在将文件移至另一个要处理的文件夹之前重命名文件。

由于我正在处理所有不同大小的文件,因此我创建了一个对象,该对象在单独的线程中检查文件以验证它是否“可用”以及何时触发事件。

当我从这个可用事件中运行重命名代码时,它可以工作。

public void RenameFile_Test()
{
    string psFilePath = @"C:\File1.xlsx";
    tgt_File target = new FileObject(psFilePath);
    target.FileAvailable += new FileEventHandler(OnFileAvailable);
    target.FileUnAvailable += new FileEventHandler(OnFileUnavailable);
}

private void OnFileAvailable(object source, FileEventArgs e)
{
    ((FileObject)source).RenameFile(@"C:\File2.xlsx");
}

我遇到的问题是,当扩展名与源文件不同并且重命名为文件时,我正在调用转换工厂,该转换工厂根据转换类型返回工厂对象,然后转换在重命名之前相应地归档。当我在单元测试中运行该特定代码时,它会工作,返回工厂对象,并且转换正确。

但是当我在这个过程中运行它时,我就开始......

        moExcelApp = new Application();

将.xls或.xlsx转换为.csv的一部分,我收到“线程被中止”错误。

有什么想法吗?

更新

有一些信息和一些关于当前应用程序如何工作的地图。

  • 运行FSW的客户端应用程序
  • On File Created事件创建传递文件路径的FileObject。
  • 在构造时,文件已经过验证:如果文件存在,则为

    Thread toAvailableCheck = new Thread(new ThreadStart(AvailableCheck));
    toAvailableCheck.Start();
    
  • AvailableCheck Method反复尝试打开文件的流读取器,直到创建了读取器或尝试次数超时。如果打开了阅读器,则会触发FileAvailable事件,否则会触发FileUnAvailable事件,并在事件中自行传回。

  • 连接客户端应用程序以从FSW的Oncreated事件中捕获这些事件。

  • OnFileAvailable方法然后调用包含excel互操作调用的重命名功能。
  • 如果文件正在重命名(未转换,扩展保持不变),则会移动将名称从旧文件名更改为新文件,如果是转换,则运行转换工厂对象,返回正确的基于源文件扩展名和目标文件名的转换类型。
  • 如果是简单的重命名,它就没有问题。如果它是一个转换(作为工厂的一部分返回的XLS到CSV对象),它首先要做的是创建一个新的应用程序对象。这就是申请炸弹的地方。

当我在线程外部测试工厂和转换/重命名过程并在其自己的单元测试中,该过程无问题。

更新

我通过执行以下操作在线程中测试了Excel Interop:

[TestMethod()]
public void ExcelInteropTest()
{
    Thread toExcelInteropThreadTest = new Thread(new ThreadStart(Instantiate_App));
    toExcelInteropThreadTest.Start();
}

private void Instantiate_App()
{
    Application moExcelApp = new Application();
    moExcelApp.Quit();
}

在应用程序实例化的行上,我得到了'类型'System.Threading.ThreadAbortException'错误的第一次机会异常。

所以我补充说;

toExcelInteropThreadTest.SetApartmentState(ApartmentState.MTA);

在线程实例化之后和线程开始调用之前仍然得到相同的错误。我认为我将不得不重新考虑设计。

1 个答案:

答案 0 :(得分:2)

有人在调用Thread.Abort()。这可能是CLR,因为未处理的异常而试图关闭程序。您可能会看到ThreadAbortException而不是真正异常的原因是因为您在不是单线程单元的线程中使用COM服务器(如Excel)。检查Thread.SetApartmentState()的文档。与FileSystemWatcher用于引发事件的线程池线程不能是STA。

同时检查“输出”窗口中是否有调试器通知,并使用“调试+异常”,“抛出”框使调试器在第一个异常处停止。