Click here to Skip to main content
15,893,564 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I'm writing a basic app to read a file sync and async. Async works fine but sync does not. When I put a breakpoint in syncRead() I get the following message:"An unhandled exception of type 'System.Threading.ThreadStateException' occurred in System.Windows.Forms.dll

Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process."
I have set the [STAThread] attribute. I'm sure it's something blindingly obvious!?!?

Here's the code:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace Streams
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]

        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace Streams
{
    public partial class Form1 : Form
    {
        FileStream fs;
        byte[] fileContents;
        AsyncCallback callback;

        public void syncRead()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.ShowDialog();
            FileStream fs;
            try
            {
                fs = new FileStream(ofd.FileName, FileMode.OpenOrCreate);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            fs.Seek(0, SeekOrigin.Begin);
            byte[] fileContents = new byte[fs.Length];
            fs.Read(fileContents, 0, (int)fs.Length);
            tbResults.Text = Encoding.UTF8.GetString(fileContents);
            fs.Close();
        }

        public Form1()
        {
            InitializeComponent();
        }
        private void fs_StateChanged(IAsyncResult asyncResult)
        {
            if (asyncResult.IsCompleted)
            {
                tbResults.Text = Encoding.UTF8.GetString(fileContents);
                fs.Close();
            }
        }
        private void btnReadAsync_Click(object sender, EventArgs e)
        {
            openFileDialog.ShowDialog();
            callback = new AsyncCallback(fs_StateChanged);
            fs = new FileStream(openFileDialog.FileName, FileMode.Open,
            FileAccess.Read, FileShare.Read, 4096, true);
            fileContents = new Byte[fs.Length];
            fs.BeginRead(fileContents, 0, (int)fs.Length, callback, null);
        }

        private void btnReadSync_Click(object sender, EventArgs e)
        {
            Thread thdSyncRead = new Thread(new ThreadStart(syncRead));
            thdSyncRead.Start();
        }
    }
}
Posted
Updated 27-Aug-12 1:31am
v2
Comments
pramod.hegde 27-Aug-12 7:54am    
Give [STAThread] attribute on public void syncRead() as well.
BrianHamilton 27-Aug-12 8:55am    
Have altered above code as follows:

[STAThreadAttribute]
public void syncRead()
{
//OpenFileDialog ofd = new OpenFileDialog();
//ofd.ShowDialog();
openFileDialog.ShowDialog();
FileStream fs;

When I run program and click the ReadSync button, the file open dialog box does not show up - it didn't before either.

1 solution

It is not possible to interact with GUI elements from different threads than the GUI thread. If you want to do this, you have to change your design. For instance creating and showing dialogs must be delegated to the GUI thread. The GUI thread being the default thread of your application.
Suppose you have a form with some edit boxes and you want to change these edit boxes text values from another thread than the GUI thread, then you need to modify your code as well, because the actual change needs to be done on the GUI thread.
I am on a business trip right now so I cannot give you an example of my own, but this involves calling invoke and using a delegate. If needed you can check if this is really needed by calling invokerequired on the control on which you want to do the change. I am quite sure for dialogs that they need to be created from the GUI thread too via the same mechanism.
An example can be found here :
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx[^]
 
Share this answer
 
Comments
BrianHamilton 27-Aug-12 9:39am    
I see what you mean, but the async GUI code functions perfectly.
Philip Stuyck 27-Aug-12 9:48am    
No, because the only GUI code you have is opening the dialog and that part does not work. Handling files is not GUI code, showing a dialog is. If you use a debugger to step through the code you can see when it jumps to the exception handler and I am quite sure it will happen here :
ofd.ShowDialog();
BrianHamilton 27-Aug-12 11:41am    
Apologies, of course - It's working now. Thanks for the link and explanation.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900