STAThread отсутствует, но он есть - PullRequest
5 голосов
/ 27 августа 2010

Вот сообщение об ошибке, которое я получаю, когда пытаюсь открыть OpenFileDialog в моей программе:

"Текущий поток должен быть установлен на один Поток квартиры (STA) в режиме перед OLE звонки могут быть сделаны. Убедитесь, что ваш Основная функция имеет атрибут STAThreadAttribute отмечено на нем. Это исключение только возникает, если отладчик подключен к процесс. "

Проблема с этим сообщением об ошибке заключается в том, что мой метод Main ДОЛЖЕН иметь атрибут 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
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

И никакие потоки не выполняются явно. Просто довольно простая программа, если честно.

EDIT2 ::

Вот полное сообщение об ошибке, включая стек вызовов

System.Threading.ThreadStateException был не обработан Сообщение = "Текущий поток должен быть установлен в однопотоковый режим (STA), прежде чем могут быть выполнены вызовы OLE. Убедитесь, что вашей основной функции помечен атрибут STAThreadAttribute. Это исключение возникает только в том случае, если к процессу подключен отладчик." Источник = "System.Windows.Forms" Трассировки стека: в System.Windows.Forms.FileDialog.RunDialog (IntPtr hWndOwner) в System.Windows.Forms.CommonDialog.ShowDialog (владелец IWin32Window) в System.Windows.Forms.CommonDialog.ShowDialog () в MSI_Comparison_GUI.Form1.btnOldFind_Click (Отправитель объекта, EventArgs e) в c: \ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Form1.cs: Form 70 в System.Windows.Forms.Control.OnClick (EventArgs e) в System.Windows.Forms.Button.OnClick (EventArgs e) в System.Windows.Forms.Button.OnMouseUp (MouseEventArgs mevent) в System.Windows.Forms.Control.WmMouseUp (сообщение & m, кнопка MouseButtons, щелчки Int32) в System.Windows.Forms.Control.WndProc (сообщение & m) в System.Windows.Forms.ButtonBase.WndProc (сообщение & m) в System.Windows.Forms.Button.WndProc (сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc (Message & m) в System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) в System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & msg) в System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 dwComponentID, причина Int32, Int32 pvLoopData) в System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (причина Int32, контекст ApplicationContext) в System.Windows.Forms.Application.ThreadContext.RunMessageLoop (причина Int32, контекст ApplicationContext) в System.Windows.Forms.Application.Run (Форма mainForm) в MSI_Comparison_GUI.Program.Main () в c: \ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Program.cs: строка 18 в System.AppDomain._nExecuteAssembly (сборка сборки, аргументы String []) в System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () в System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта) в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart () InnerException:

Ответы [ 4 ]

14 голосов
/ 27 августа 2010

Возможно, вы столкнулись со следующей проблемой, о которой сообщалось в Connect 1 :

.vshost.exe вызывает неправильную модель потоков, используемую при отладке .exe, если в одном и том же каталоге bin существует .dll с тем же именем

В соответствии с этой проблемой случается, что процесс размещения Visual Studio, то есть myprogram.vshost.exe, устанавливает неверное состояние квартиры, когда у вас есть и myprogram.exe , и myprogram. Файл dll в вашей выходной папке.

Проблема может быть связана с какой-то более старой версией Visual Studio (2005), и я не смог воспроизвести ее с использованием VS 2010.

Очевидным обходным решением будет изменение имени библиотеки DLL или перемещение библиотеки DLL в другую папку.

Ситуация могла возникнуть из-за того, что вы изменили тип вывода вашего проекта с библиотеки классов на приложение Windows.

1 Неясно, подтверждена ли эта проблема Microsoft или нет, она просто говорит, что проблема не входит в обязанности группы разработчиков VS.

6 голосов
/ 27 августа 2010

У вас есть невозможный след стека. Ясно, что многопоточность не является причиной проблемы, все выполняется в основном потоке, а атрибут [STAThread] в вашем методе Main устанавливает состояние квартиры. Трассировка стека показывает, что это действительно точка входа.

Что ж, плохие новости, какая-то надстройка фарсирует с вашей основной веткой. Делать что-то неприятное, например, вызывать CoUninitialize слишком много раз. У меня такое случилось со мной однажды, мне потребовался месяц, чтобы найти это. Начните диагностировать это с Project + Properties, вкладкой Debug, отметьте «Включить отладку неуправляемого кода». Это позволяет увидеть, какие DLL загружаются в вашу программу, это показано в окне «Вывод».

Первый шаг - когда диалоговое окно отображает нормально время first , но не проходит время second . Тогда у вас есть какой-то обработчик расширения оболочки, который проник в вашу программу. Воспользуйтесь утилитой SysInternals AutoRuns и отключите любой обработчик расширения оболочки, который не был создан Microsoft.

Становится все труднее, когда диалог сразу терпит неудачу. Затем используйте Debug + Windows + Modules и просмотрите список библиотек DLL. Обратите внимание на то, откуда они пришли, как показано в столбце «Путь». Не доверяйте всему, что не крякает, как .NET или Microsoft DLL. Особенно отсутствие файла символов при включении Microsoft Symbol Server. Хороший способ добиться успеха - сравнить этот список с тем, который вы видите на другом компьютере, у которого нет этой проблемы.

У меня есть военная история об этом. Мой COM-код зависал на сотнях машин, и все, что мне нужно было сделать, это мини-дамп. У меня ушел месяц на то, чтобы найти источник проекта с открытым исходным кодом ffdshow. Очень широко распространен, с использованием разных имен. В ней была ошибка, вызывающая CoUnitialize в два раза больше. Ошибка присутствовала в выпусках в течение двух лет, но была исправлена ​​около полутора лет назад. Очень трудно диагностировать, я не приблизился к этому, пока не начал смотреть на старые выпуски. Если вы видите ffdshow в вашем окне модулей, то вы близки:)

Удачи, дайте нам знать злодея.

3 голосов
/ 27 августа 2010

Не могу сказать без кода. Если консольное приложение, добавьте следующее перед вызовом метода:

Console.Write(System.Threading.Thread.CurrentThread.ApartmentState);

в противном случае

MessageBox.Show(System.Threading.Thread.CurrentThread.ApartmentState);

и посмотрите, что ДЕЙСТВИТЕЛЬНО состояние квартиры в квартире ДЕЙСТВИТЕЛЬНО.

0 голосов
/ 27 августа 2010

Попробуйте установить точки останова в основной процедуре, где создается диалоговое окно и где оно используется. Затем посмотрите, в каком потоке (ах) вы находитесь. Кроме того, проверьте, какое значение Thread.CurrentThread.GetApartmentState() находится в этих точках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...