【发布时间】:2017-04-24 14:59:44
【问题描述】:
当我使用 Office.Interop 库重构一些用于文档生成的旧 C# 代码时,我发现了这一点,因为它在调用函数时使用了 UI 上下文,所以它被阻塞了
例子
private void btnFooClick(object sender, EventArgs e)
{
bool documentGenerated = chckBox.Checked ? updateDoc() : newDoc();
if(documentGenerated){
//do something
}
}
决定这样改变它以减少阻塞 UI
private async void btnFooClick(object sender, EventArgs e)
{
bool documentGenerated; = chckBox.Checked ? updateDoc() : newDoc();
if(chckBox.Checked)
{
documentGenerated = await Task.Run(() => updateDoc()).ConfigureAwait(false);
}
else
{
documentGenerated = await Task.Run(() => newDoc()).ConfigureAwait(false);
}
if(documentGenerated){
//do something
}
}
它正在抛出这样的错误
当前线程必须设置为单线程单元 (STA) 模式 在进行 OLE 调用之前
为什么会发生这种情况以及可能的解决方法是什么?
【问题讨论】:
-
你正在 updateDoc() 中做一些你不应该在工作线程中做的事情。我们看不到它。从您使用剪贴板或 OpenFileDialog 之类的 shell 对话框的异常消息来看,与 Office 互操作无关。不要那样做。请记住,互操作代码无论如何都在 UI 线程上运行,COM 会自动保持线程安全,因此您可能不会领先。
-
@HansPassant 好吧,是的,至少看到了
MessageBox来电 -
@HansPassant 哈哈,剪贴板也在那里使用。 3.5年开发经验,对这类问题一窍不通,有点害怕
-
是的,害怕穿线的野兽,只有这样才能避免被活生生吃掉。它不是 MessageBox,它默默地让你做错了。盒子出现在另一个窗口后面的可能性总是不错的,用户永远不会看到它,一切都停止了。它是剪贴板。
-
@HansPassant wellp,有没有关于 STA、MTA 之类的好的实践文章?
标签: c# multithreading office-interop