Подтвердить что ты не робот

С# WinForms: как установить основную функцию STAThreadAttribute

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

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

В соответствии с этим:

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

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

в правом верхнем углу перед Application.Run.

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

4b9b3361

Ответ 1

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

Invoke((Action)(() => { saveFileDialog.ShowDialog() }));

Ответ 2

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

Итак, ваш основной метод должен выглядеть так:

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

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

Ответ 3

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

var thread = new Thread(new ParameterizedThreadStart(param => { saveFileDialog.ShowDialog(); }));
 thread.SetApartmentState(ApartmentState.STA);
thread.Start();

Ответ 4

Добавьте следующий код на 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();}

Ответ 5

В вашем MainForm:

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();
 });