C # WinForms: как установить основную функцию STAThreadAttribute - PullRequest
24 голосов
/ 16 июня 2011

Я получаю следующее исключение при вызове saveFileDialog.ShowDialog() в фоновом потоке:

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

Согласно это :

Чтобы устранить проблему, вставьте утверждение:

Threading.Thread.CurrentThread.ApartmentState = Threading.ApartmentState.STA;

в основном прямо перед Заявление. Выполнение заявления.

Но оператор Application.Run находится в Program.cs, который выглядит как сгенерированный код, поэтому любые изменения могут быть неожиданно потеряны. Кроме того, я не смог найти способ установить текущую нить в STA в свойствах проекта или основной формы, но, возможно, я смотрю не в том месте. Как правильно вызывать saveFileDialog.ShowDialog() в фоновом потоке?

Ответы [ 5 ]

45 голосов
/ 11 декабря 2012

Решение очень простое;Просто добавьте это поверх метода Main [STAThread]

Так ваш основной метод должен выглядеть следующим образом

 [STAThread]
 static void Main(string[] args)
 {
     ....
 }

Он работает для меня.

25 голосов
/ 16 июня 2011

ShowDialog () не следует вызывать из фонового потока - используйте Invoke (..).

Invoke((Action)(() => { saveFileDialog.ShowDialog() }));
11 голосов
/ 16 июня 2011

это должно работать, если вы создаете поток, в котором вы вызываете showDialog:

var thread = new Thread(new ParameterizedThreadStart(param => { saveFileDialog.ShowDialog(); }));
 thread.SetApartmentState(ApartmentState.STA);
thread.Start();
7 голосов
/ 29 января 2013

Добавьте следующий код на FormLoad

private void Form1_Load(object sender, EventArgs e)
{
    Thread myth;
    myth = new Thread(new System.Threading.ThreadStart(CallSaveDialog)); 
    myth.ApartmentState = ApartmentState.STA;
    myth.Start();
}

Здесь CallSaveDialog - это тема, и здесь вы можете назвать ShowDialog вот так

void CallSaveDialog(){saveFileDialog.ShowDialog();}
1 голос
/ 16 июня 2011

На вашей главной форме:

if (this.InvokeRequired) { 
 this.Invoke(saveFileDialog.ShowDialog()); 
} else { 
 saveFileDialog.ShowDialog(); 
}

Или, если у вас будут другие методы, которые необходимо запустить из потока пользовательского интерфейса:

  private void DoOnUIThread(MethodInvoker d) {
     if (this.InvokeRequired) { this.Invoke(d); } else { d(); }
  }

Затем вызовите свой метод как таковой:

 DoOnUIThread(delegate() {
    saveFileDialog.ShowDialog();
 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...