STAThread缺失,但它就在那里
这是我尝试在程序中打开OpenFileDialog时收到的错误消息:
“在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式。确保主函数上标记了STAThreadAttribute。只有在调试器附加到进程时才会引发此exception。”
此错误消息的问题是我的Main方法DOES附加了STAThread属性。 我不知道如何处理这个问题。 如果它已经存在,我怎么能添加一些东西。 加倍它并不是一个好选择,我尝试删除它,构建应用程序,添加它并再次构建它没有成功。 我只是不明白。
private void btnOldFind_Click(object sender, EventArgs e) { openFileDialog1.Multiselect = false; openFileDialog1.FileName = ""; openFileDialog1.ShowHelp = false; openFileDialog1.AutoUpgradeEnabled = true; openFileDialog1.InitialDirectory = @"C:\"; openFileDialog1.Filter = "Microsoft Installer (*.msi)|*.msi|All Files (*.*)|*.* "; openFileDialog1.FilterIndex = 1; openFileDialog1.RestoreDirectory = true; if (openFileDialog1.ShowDialog() == DialogResult.OK) { textBoxOldInstallation.Text = openFileDialog1.FileName; } }
主要方法是:
static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }
并且没有明确地进行线程化。 说实话,这是一个非常基本的计划。
EDIT2 ::
这是完整的错误消息,包括调用堆栈
System.Threading.ThreadStateException未处理Message =“当前线程必须设置为单线程单元(STA)模式,然后才能进行OLE调用。确保您的Main函数标记了STAThreadAttribute。仅当调试器是附在过程中。“ Source =“System.Windows.Forms”StackTrace:位于System.Windows.Forms.Forms.CommonDialog.ShowDialog的System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window所有者)的System.Windows.Forms.FileDialog.RunDialog(IntPtr hWndOwner)中。 )在System.Windows.Forms.Control的c:\ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Form1.cs:第70行中的MSI_Comparison_GUI.Form1.btnOldFind_Click(Object sender,EventArgs e)处。 OnClick(EventArgs e)在System.Windows.Forms.OnClick上的System.Windows.Forms.Button.OnClick(EventArgs e)(SystemErgs e),System.Windows.Forms.Control.WmMouseUp(Message&m,MouseButtons按钮,在System.Windows上的System.Windows.Forms.Button.WndProc(Message&m)的System.Windows.Forms.ButtonBase.WndProc(Message&m)处的System.Windows.Forms.Control.WndProc(Message&m)处进行Int32单击)。 System.Windows.Forms.NativeWindow.Debu的System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&m)中的Forms.Control.ControlNativeWindow.OnMessage(Message&m) System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop上的System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&msg)中的ggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)系统中的System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason,ApplicationContext context)中的System32.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext context)中的(Int32 dwComponentID,Int32 reason,Int32 pvLoopData) .Windows.Forms.Application.Run(Form mainForm)位于c:\ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Program.cs:System 18中的MSI_Comparison_GUI.Program.Main()。 System.Threading.T上的Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()中的System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args)中的AppDomain._nExecuteAssembly(程序集,String [] args) System.Threading.ThreadHelper.ThreadStart()中的System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态)中的hreadHelper.ThreadStart_Context(Object state):InnerException:
可能是您遇到Connect 1上报告的以下问题:
.vshost.exe在调试.exe时强制使用错误的线程模型,如果同一个bin目录中存在同名的.dll
根据该问题,当您在输出文件夹中同时包含myprogram.exe和myprogram.dll文件时,会发生Visual Studio的托管过程,即myprogram.vshost.exe强制执行错误的单元状态。
问题可能是特定于某些旧版本的Visual Studio(2005),我无法使用VS 2010重现它。
显而易见的解决方法是更改dll的名称或将dll移动到另一个文件夹。
由于您将项目的输出类型从类库更改为Windows应用程序,因此可能会出现这种情况。
1目前还不清楚这个问题是否得到了微软的确认,它只是说这个问题超出了VS产品团队的责任范围。
你有一个不可能的堆栈跟踪。 很明显,线程不是问题的原因,一切都在主线程上运行,Main方法的[STAThread]属性正在设置单元状态。 堆栈跟踪显示它确实是入口点。
好吧,坏消息,某种附加function正在与你的主线程相悖。 做一些令人讨厌的事情,比如多次调用CoUninitialize。 我曾经遇到过这种情况,花了我一个月才找到它。 使用Project + Properties,Debug选项卡开始诊断,勾选“启用非托管代码调试”。 这可以让你看到哪些DLL被加载到你的程序中,它显示在Output窗口中。
第一个引导是第一次对话框显示正常但第二次失败时。 然后你有一些shell扩展处理程序,它已经进入你的程序。 使用SysInternals的AutoRuns实用程序并禁用任何非Microsoft生成的shell扩展处理程序。
当对话框立即失败时,它会变得更难。 然后使用Debug + Windows + Modules并浏览DLL列表。 注意它们来自何处,显示在“路径”列中。 不信任任何不像.NET或Microsoft DLL那样嘎嘎叫的东西。 启用Microsoft Symbol Server时,特别是没有符号文件是一个主角。 与此相关的一个好方法是将该列表与您在另一台没有此问题的计算机上看到的列表进行比较。
我确实有一个关于此的战争故事。 我的COM代码在数百台机器上崩溃了,我所要做的只是一个小型机。 花了我一个月的时间来发现一个名为ffdshow的开源项目。 分布广泛,使用不同的名称。 它有一个错误,两次调用CoUnitialize太多了。 该漏洞存在于发布中两年,但在一年半前得到修复。 很难诊断,在我开始查看旧版本之前,我没有接近它。 如果你在模块窗口中看到ffdshow,那么你就接近:)
祝你好运,让我们知道邪恶的行为者。
不能没有代码说。 如果是控制台应用程序,请在调用方法之前添加以下内容:
Console.Write(System.Threading.Thread.CurrentThread.ApartmentState);
除此以外,
MessageBox.Show(System.Threading.Thread.CurrentThread.ApartmentState);
并看看线程公寓状态真的是什么。
尝试在主过程,创建对话框的位置以及使用位置设置断点。 然后查看您实际所在的线程。另外,检查Thread.CurrentThread.GetApartmentState()
的值是在这些点上。