Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Threading threads
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:
 
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 27-Aug-12 2:26am
Edited 27-Aug-12 2:31am
Wes Aday94.3K
v2
Comments
pramodhegde88 at 27-Aug-12 7:54am
   
Give [STAThread] attribute on public void syncRead() as well.
BrianHamilton at 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

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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[^]
  Permalink  
Comments
BrianHamilton at 27-Aug-12 9:39am
   
I see what you mean, but the async GUI code functions perfectly.
Philip Stuyck at 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 at 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)

  Print Answers RSS
0 OriginalGriff 365
1 Sergey Alexandrovich Kryukov 329
2 CPallini 270
3 Afzaal Ahmad Zeeshan 204
4 DamithSL 194
0 OriginalGriff 5,515
1 DamithSL 4,451
2 Maciej Los 3,902
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,175


Advertise | Privacy | Mobile
Web01 | 2.8.141216.1 | Last Updated 27 Aug 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100