SaveFileDialog: InvalidOperationException due to owner parameter in multithreaded application

Sorry for the long post, but I tried to explain the problem in great detail so that there would be no confusion. The last sentence contains the actual question.

I am programming a multi-threaded application with C # /. NET

The application consists of a main window that visualizes the data coming from the pressure sensor. Sensor data is acquired in its own stream.

Data is also logged in an instance of the class ListView:

enter image description here

It is possible to save the recorded data to a file on disk using the "Save" button (should open an instance of the .NET class SaveFileDialog).

SaveFileDialog . SaveFileDialog.ShowDialog():

System.InvalidOperationException        = " : " tlpMain " , , ."        = "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 = " (STA) , OLE . , STAThreadAttribute, . , ".         = "System.Windows.Forms"

- , SaveFileDialog , ( "unclickable" ) ?

.

+3
3

-, , "Managed Debugging Assistant" . . , , Visual Studio.

, , , . ISynchronizeInvoke, Invoke BeginInvoke, , .

. OpenSaveFileDialog, , SaveFileDiaglog, , , . . . Form Control . .

+2

.

, .

,

-

.

GUI Microsoft Windows, .

, , ( GUI ) .

Window Component Object Model (COM) :

:

( " " ) ApartmentState STA

...
ThreadStart threadStart = delegate { RunMainWindow(mainWindow); };
Thread mainWindowThread = new Thread(threadStart);

mainWindowThread.SetApartmentState(ApartmentState.STA);
mainWindowThread.Start();
...

"" ( ):

private void bSave_Click(object sender, EventArgs e)
{
            OpenSaveFileDialog();
}

" OpenSaveFileDialog" ( ):

private void OpenSaveFileDialog()
{
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            ...

            DialogResult pressedButton = saveFileDialog.ShowDialog();
            ...
}

- , - .

.

+1

Follow this blogpost for Microsoft: http://blogs.msdn.com/b/smondal/archive/2011/05/11/10059279.aspx

Just two methods and you're done!

0
source

All Articles