Извините за длинный пост, но я попытался объяснить проблему очень подробно, чтобы не возникало путаницы.Последнее предложение содержит актуальный вопрос.
Я программирую многопоточное приложение на C # /. NET.
Приложение состоит из главного окна, которое визуализирует данные, поступающие издатчик давления.Данные датчика собираются в собственном потоке.
Данные также регистрируются в экземпляре класса ListView
:
Существует возможностьсохранить зарегистрированные данные в файл на диске с помощью кнопки «Сохранить» (должен открыть экземпляр класса .NET SaveFileDialog
).
Этот SaveFileDialog
также выполняется в собственном потоке.Теперь возникает проблема при вызове метода SaveFileDialog.ShowDialog()
:
System.InvalidOperationException не обработан. Message = "Операция с несколькими потоками недопустима: доступ к элементу управления tlpMain осуществляется из потока, отличного от потока, в котором он находился.создано на."Source = "System.Windows.Forms"
Проблема возникает из-за того, что владелец (главное окно) SaveFileDialog работает в другом потоке.
Вот код, который создает поток для SaveFileDialog ():
private void bSave_Click(object sender, EventArgs e)
{
Thread saveFileDialog = new Thread(OpenSaveFileDialog);
saveFileDialog.SetApartmentState(ApartmentState.STA);
saveFileDialog.Start();
}
Код для метода OpenSaveFileDialog ():
private void OpenSaveFileDialog()
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Text Files (*.txt)|*.txt|CSV (*.csv)|*.csv|All Files (*.*)|*.*";
saveFileDialog.FilterIndex = 0;
/* Call "ShowDialog" with an owner ("this.Parent") to achieve, so that
* the parent window is blocked and "unclickable".
*
* Danger of an "InvalidOperationException" because "this.Parent" control
* is running (was created) in another thread.
* But "this.Parent" should not be modified by this method call.
*/
DialogResult pressedButton = saveFileDialog.ShowDialog(this.Parent);
...
Выдается только InvalidOperationException / отображается при запуске приложения с помощью отладчика Visual Studio.Пока это не проблема - пока приложение работает "нормально".
Но я бы хотел избежать этой проблемы.
Я пытался построить метод-обертку (SaveFileDialog):
private void OpenSaveFileDialog()
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
...
SaveFileDialog(saveFileDialog, this.Parent);
}
Метод обертки:
private void SaveFileDialog(SaveFileDialog saveFileDialog, Control owner)
{
if (owner.InvokeRequired)
BeginInvoke(new dSaveFileDialog(SaveFileDialog), new object[] { saveFileDialog, owner });
else
{
DialogResult pressedButton = saveFileDialog.ShowDialog(owner);
...
Это приводит к TargetInvocationException
, хотя метод Main()
помечен [STAThreadAttribute]
:
InnerException:System.Threading.ThreadStateException Message = "Для выполнения OLE-вызовов текущий поток должен быть переведен в однопотоковый режим (STA). Убедитесь, что в вашей функции Main помечен атрибут STAThreadAttribute. Это исключение возникает только в том случае, если к отладчику подключенпроцесс."Source = "System.Windows.Forms"
Кто-нибудь знает, как открыть SaveFileDialog
таким образом, чтобы главное окно было заблокировано ("не кликабельно") без(нить) беда?
Спасибо.