2015-08-19 2 views
2

. Вы можете найти много похожих вопросов на SO, но никто (как я вижу) не рассматривает ситуацию, когда ваша логика должна что-то вернуть.InvalidOperationException: вызывающий поток должен быть STA, потому что многие компоненты пользовательского интерфейса требуют этого

В этом примере кода у меня есть простой CustomMessageBox (это окно), которое должно вернуть что-то, введенное пользователем.

public class CustomMessageBox 
{ 
    private string Value 
    { 
     get 
     { 
      return txt_box.Text; 
     } 
    } 

    private CustomMessageBox() 
    { 
     InitializeComponent(); 
    } 

    public static string Show(string caption = "Enter data") 
    { 
     CustomMessageBox cmb = new CustomMessageBox(); 
     cmb.txt_block.Text = caption; 

     cmb.ShowDialog(); 

     return cmb.Value; 
    } 
} 

Так что, когда Show метод вызывается BackgroundWorker, исключение брошено в первой строке, когда конструктор пытается выполнить. Исключение сообщение

An exception of type 'System.InvalidOperationException' occurred in 
PresentationCore.dll but was not handled in user code 


Additional information: The calling thread must be STA, 
because many UI components require this. 

Ничего нового, но я не могу найти решение этой проблемы, и я не могу сделать нить быть STA. Show Подпись метода должна быть такой же: возьмите строку и строку возврата.

Как обычно такие вещи должны быть разрешены?

+0

вы можете использовать диспетчер.Инвестию, чтобы поток был STA – daniel

+0

Любой пример с возможностью возврата значения из исполнения, пожалуйста. –

+0

Я обычно делал это наоборот (по крайней мере, в WinForms): вместо того, чтобы что-то возвращать, я подписался на Close-event и получил значение, которое мне нужно в обработчике событий. –

ответ

-1
public static string Show(string caption = "Enter data") 
{ 
    Application.Current.Dispatcher.Invoke(new Action(() => 
    { 
     CustomMessageBox cmb = new CustomMessageBox(); 
     cmb.txt_block.Text = caption; 
     cmb.ShowDialog(); 
    })); 
    return cmb.Value; 
} 
+0

«Исключение типа« System.InvalidOperationException »произошло в WindowsBase.dll, но не обрабатывалось в коде пользователя Дополнительная информация: вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток.» –

+0

Custom окно создано, но я все еще не могу вернуть значение. –

+0

CustomMessageBox cmb = null; Application.Current.Dispatcher.Invoke (новое действие (() => { CMB = новый CustomMessageBox(); cmb.txt_block.Text = заголовок; cmb.ShowDialog();} )); return cmb.Value; –

1

Вы не можете вызвать компонент пользовательского интерфейса от рабочего стола. Это ближайшая причина вашей проблемы. Все компоненты пользовательского интерфейса должны быть созданы и взаимодействовать с потоком пользовательского интерфейса. Вот почему в некоторых случаях у нас есть сумасшедшая логика для вызова операций с компонентами пользовательского интерфейса - в приложении работает только один поток пользовательского интерфейса.

Программа, которая требует, чтобы элемент пользовательского интерфейса, который был заполнен из фонового процесса, должен быть перепроектирован таким образом, чтобы операция была разделена на две или более единицы работы, так что это требование для работы с пользовательским интерфейсом из фона устранено.

См. WPF and background worker and the calling thread must be STA.

+0

Это объясняет, почему возникают исключения. Но почему я только см. исключения в окне вывода отладки? Почему он не работает молча, вместо отображения сообщения об ошибке? –

+0

Я не совсем уверен - обычно вы не запускаете неправильно сконфигурированную программу, подобную этой, в режиме производства. – theMayer

Смежные вопросы

 Смежные вопросы