0

When debugging my program, as soon as it hits this line, it crashes:

if (fbd.ShowDialog() == DialogResult.OK)

The errors I get are

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.

And

Cannot obtain value of local or argument as it is not available at this instruction pointer, possibly because it has been optimized away

I have no clue why this is happening. The line in question is at the very beginning of the program, there is no multi-threading that I am aware of (at least none that I intentionally developed), and the error only appears during debug, not in the build.

I have looked in to these errors, and have tried these solutions for the Multi-Threading, and these solutions for the "optimized away" issue, but neither made any difference.

I have the belief that this program was initially built as a Console application, then changed later to a Windows application, as I needed to add a reference to System.Windows.Forms (which is what the program is complaining about), so that I could use the MessageBox.

Here is my Code:

Main

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlirAdept_Plugin
{
    class Program
    {

        static void Main(string[] args)
        {            
            //Get list of files & extract Meta Data
            FlirFileList imageList = new FlirFileList();
             imageList.FlirJpg();
        }
    }
} 

FlirFileList

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Windows.Forms;


namespace FlirAdept_Plugin
{
    //Gets the image files from a specified directory and extracts the metadata if there, if not, just returns the file directory and name
    class FlirFileList
    {
        int textLength = 0;
        string[] flirFiles;
        string line = "";
        string findText = ".0 index";
        string fileName = "";
        string passString = "";
        string inPathString = @"C:\Users\Frank\Desktop\FLIR\Thermo images";   // where to read from
        string outPathFileString = null; // where to write to
        FolderBrowserDialog fbd;
        SaveFileDialog sfd;
        


        public void FlirJpg()           
        {
            Console.WriteLine("All new FLIR images should be in    C:\\Users\\Frank\\Desktop\\FLIR\\Thermo images /n");
            Console.WriteLine("CSV file will be written to         C:\\Users\\Frank\\Desktop\\FLIRb /n");

            Stream sw = null;

            sfd = new SaveFileDialog();
            sfd.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
            sfd.FilterIndex = 2;
            sfd.RestoreDirectory = true;

            fbd = new FolderBrowserDialog();

            MessageBox.Show("Please select the folder to scan...");

            if (fbd.ShowDialog() == DialogResult.OK) // Crashes here
            {
                inPathString = fbd.SelectedPath.ToString();
            }

            MessageBox.Show("Please select where the file will be saved...");

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                if ((sw = sfd.OpenFile()) != null)
                {
                    //[etc...]

Please let me know if there is additional information required.

Community
  • 1
  • 1
Ben
  • 2,433
  • 5
  • 39
  • 69
  • You need a `[STAThread]` attribute above `Main()`. – CodeCaster Apr 26 '18 at 07:01
  • 1
    Whilst just adding `STAThread` to `Main` *may* work for `ShowDialog`, it's not really honouring the STA "contract" if you're not also pumping window messages. Really, better to start again from the windows form template and copy applicable code across so that you really are being a "good" STA citizen (the window message pump in standard windows forms applications is hidden inside the `Application.Run()` call). – Damien_The_Unbeliever Apr 26 '18 at 07:07
  • @Damien don't `MessageBox` and `FileDialog` have their own message pump? – CodeCaster Apr 26 '18 at 07:22
  • 1
    They do - and so you're safe now so long as you're only using those dialogs. But you've also opened the path to temptation by pulling in all of `System.Windows.Forms`. And if you start using other bits ("hey, I'll also put a `NotifyIcon` in") you'll start getting odd errors if you've not been a good citizen. – Damien_The_Unbeliever Apr 26 '18 at 07:24
  • You'll also get problems relating to not honouring the STA "contract" if you start working with many COM objects too. – Damien_The_Unbeliever Apr 26 '18 at 08:32
  • @Damien - you are overstating the promise requirements too much, ShowDialog() is in fact good enough. What is important is to keep the promise while an app displays a window. So that the code you don't know about gets serviced. Like shell extensions, UI automation, drag+drop, window hooks. If there is no window anymore then a lot of potential misery disappears. The OP has different battles to fight, he's showing a dialog without an owner and a window without a taskbar button. – Hans Passant Apr 26 '18 at 10:01
  • @CodeCaster the `[STAThread]` fixed it. What I don't understand though is why? – Ben Apr 26 '18 at 23:09

0 Answers0