Windows 应用程序。线程中止问题

发布于 2024-10-09 02:50:32 字数 2333 浏览 5 评论 0原文

我正在开发一个应用程序,该应用程序必须根据放置在文件观察器正在监视的文件夹中的文件做出具体决策。

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

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

当我从这个可用事件内部运行重命名代码时,它起作用了。

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。
  • 在构建时验证文件:如果文件存在则为 true,

    Thread toAvailableCheck = new Thread(new ThreadStart(AvailableCheck));
    toAvailableCheck.Start();
    
  • AvailableCheck 方法会重复尝试打开文件的流读取器,直到创建读取器或尝试次数超时。如果读取器已打开,则它会触发 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);

在线程实例化之后和线程启动调用之前,仍然遇到相同的错误。我觉得我必须重新考虑设计。

I'm working on an application that has to make specific decisions based on files that are placed into a folder being watched by a file watcher.

Part of this decision making process involves renaming files before moving them off to another folder to be processed.

Since I'm working with files of all different sizes I created an object that checks the file in a seperate thread to verify that it is "available" and when it is it fires an event.

When I run the rename code from inside this available event it works.

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

The problem I'm running into is that when the extensions are different from the source file and the rename to file I am making a call to a conversion factory that returns a factory object based on the type of conversion and then converts the file accordingly before doing the rename. When I run that particular piece of code in unit test it works, the factory object is returned, and the conversion happens correctly.

But when I run it within the process I get up to the...

        moExcelApp = new Application();

part of converting an .xls or .xlsx to a .csv and i get a "Thread was being Aborted" error.

Any thoughts?

Update:

There is a bit more information and a bit of map of how the application works currently.

  • Client Application running FSW
  • On File Created event Creates a FileObject passing in the path of the file.
  • On construction the file is validated: if file exists is true then,

    Thread toAvailableCheck = new Thread(new ThreadStart(AvailableCheck));
    toAvailableCheck.Start();
    
  • The AvailableCheck Method repeatedly tries to open a streamreader to the file until the reader is either created or the number of attempts times out. If the reader is opened, it fires the FileAvailable event, if not it fires the FileUnAvailable event, passing back itself in the event.

  • The client application is wired to catch those events from inside the Oncreated event of the FSW.

  • the OnFileAvailable method then calls the rename functionality which contains the excel interop call.
  • If the file is being renamed (not converted, extensions stay the same) it does a move to change the name from the old file name to the new, and if its a conversion it runs a conversion factory object which returns the correct type of conversion based on the extensions of the source file and the destination file name.
  • If it is a simple rename it works w/o a problem. If its a conversion (which is the XLS to CSV object that is returned as a part of the factory) the very first thing it does is create a new application object. That is where the application bombs.

When i test the factory and conversion/rename process outside of the thread and in its own unit test the process works w/o a problem.

Update:

I tested the Excel Interop inside a thread by doing this:

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

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

And on the line where the application is instatntiated I got the 'A first chance exception of type 'System.Threading.ThreadAbortException' error.

So I added;

toExcelInteropThreadTest.SetApartmentState(ApartmentState.MTA);

after the thread instantiation and before the thread start call and still got the same error. I'm getting the notion that I'm going to have to reconsider the design.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冬天旳寂寞 2024-10-16 02:50:32

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

另请检查“输出”窗口中的调试器通知,并使用“调试 + 异常”、“抛出”框使调试器在出现第一个异常时停止。

Somebody is calling Thread.Abort(). That could be the CLR, trying to shut your program down because of an unhandled exception. The reason you might see the ThreadAbortException instead of the real exception is because you are using a COM server (like Excel) in a thread that isn't a single threaded apartment. Check the docs for Thread.SetApartmentState(). Threadpool threads like the ones that FileSystemWatcher uses to raise events cannot be STA.

Also check the Output window for debugger notifications and use Debug + Exceptions, Thrown box to make the debugger stop on the first exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文