Bil*_*ill 3 c# com multithreading visual-studio
我构建了一个Microsoft Word的附加组件.当用户单击某个按钮时,它会运行许多将Microsoft Word文档列表导出为Filtered HTML的进程.这很好用.
代码落后的地方是处理大量文件.文件转换完成后我调用下一个函数,应用程序崩溃,我从Visual Studio获取此信息:
托管调试助手'DisconnectedContext'在'C:\ Program Files\Microsoft Office\root\Office16\WINWORD.EXE'中检测到问题.
附加信息:此RuntimeCallableWrapper转换到COM上下文0x56255b88失败,并显示以下错误:系统调用失败.(来自HRESULT的异常:0x80010100(RPC_E_SYS_CALL_FAILED)).这通常是因为创建此RuntimeCallableWrapper的COM上下文0x56255b88已断开连接或正忙于执行其他操作.从当前COM上下文释放接口(COM上下文0x56255cb0).这可能会导致损坏或数据丢失.要避免此问题,请确保所有COM上下文/公寓/线程都保持活动状态并可用于上下文转换,直到应用程序完全使用表示其中的COM组件的RuntimeCallableWrappers完成.
经过一些测试,我意识到如果我只是在文件转换后删除所有代码,就没有问题.要解决此问题,我将其余代码放在另一个按钮中.
问题是我不想给用户两个按钮.阅读各种其他线程后,听起来我的代码有内存或线程问题.我正在阅读的答案并没有帮助我真正理解下一步该做什么.
我觉得这就是我想要做的事情:
1-运行转换.2-转换中关闭线程/清理内存问题.3-继续运行代码.
不幸的是,我真的不知道怎么做#2或者甚至可能.非常感激您的帮忙.
或者它正在忙着做别的事情
您获得的托管调试助手诊断非常糟糕,但这是准确描述真实问题的消息的一部分.你有一个firehose问题,这是与线程相关的第三个最常见的问题.这个事故难以诊断,因为这在Word管道中出错了,而不是你的代码.
试着不要自己犯同样的gobbledygook罪,出了什么问题就是你在Office程序中进行的互操作调用排队等待轮到他们执行了.错误代码提示的基础"系统调用"是PostMessage().只要有队列,队列就有可能变得太大.当生产者(您的程序)正在添加项目时,发生的事情远远快于消费者(Office程序)删除它们.消防问题.除非生产者放慢速度,否则队列将无限制地增长,如果允许无限增长,则某些事情将会失败,至少该过程会耗尽内存.
不允许接近这个问题.PostMessage()使用的基础队列受操作系统保护.当队列已包含10,000条消息时,Windows无法通过呼叫.这是一个致命的错误,RPC不知道如何从中恢复,或者更确切地说不应该尝试从中恢复.有些不对劲并且不漂亮.它会向您的程序返回一个错误代码,以告诉您相关信息.这是RPC_E_SYS_CALL_FAILED.在您的程序中没有更好的事情发生,CLR也不知道如何从中恢复,您的代码也不知道.所以节目结束了,你所做的互操作丢失了,并没有被Word执行.
为这个棘手的问题找到一个完全可靠的解决方法并不是那么简单.请注意,这可能发生在任何互操作调用上,因此捕获异常并再次尝试是非常不切实际的.但请记住,Q + D修复非常简单.一个明显的问题是你的程序运行得太快,使用Thread.Sleep()或Task.Delay()调用减慢它的速度非常粗糙,但总会解决问题.好吧,假设你延迟了.
我想,但不知道一个事实,因为没有人发布过repro代码,这个问题也与你的程序中使用控制台模式应用程序或工作线程有关.如果它是控制台模式应用程序,则尝试将[STAThread]属性应用于Main()方法.如果它是工作线程,则在启动线程之前调用Thread.SetApartmentState(),但要注意,在该工作线程上创建Application接口也非常重要.否则不是加载项的解决方法.
如果这些变通办法都没有效果或太不实用,那么请考虑您可以自动减慢程序速度,并通过偶尔从Office程序中读取内容来确保队列清空.有点傻,任何财产吸气者都会这么做.在Office程序赶上之前,您无法获得属性值.这仍然可能失败,互操作也有60秒的超时时间.但是你可以解决这个问题,你可以在你的程序中调用CoRegisterMessageFilter()来安装一个在超时跳闸时运行的回调.非常gobbledygooky,但剪切和粘贴代码很容易获得.
| 归档时间: |
|
| 查看次数: |
715 次 |
| 最近记录: |