Solution of OpenFileDialog using thread to report error in. NET

  • 2021-10-16 01:27:54
  • OfStack

Yesterday, when doing a small demo read by NPOI, use OpenFileDialog to open the file. The initial writing method is written directly in the button click event, and an error will be reported. The code is as follows:


OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Microsoft Office Excel(*.xls;*.xlsx)|*.xls;*.xlsx";
ofd.FilterIndex = 1;
ofd.RestoreDirectory = true;


if (ofd.ShowDialog() == DialogResult.OK)
{
   // Detect whether the open file path is an empty address 
   if (!string.IsNullOrEmpty(ofd.FileName))
   {
          ReadFromExcelFile(ofd.FileName);
   }
   else
   {
          this.textBox1.Text = " Please open excel Documents ";
    }
} 

Or directly


using(OpenFileDialog ofd = new OpenFileDialog()){   ofd.ShowDialog();   }

These two kinds, no matter which way they are written, will report errors when the code is executed. The specific errors are:

An unhandled exception of type "System. Threading. ThreadStateException" occurs in System. Windows. Forms. dll

Additional information: Before OLE can be called, the current thread must be set to single-threaded unit (STA) mode. Make sure your Main function is marked with STAThreadAttribute. This exception is thrown only if a debugger is attached to the process.

In this case, querying on the Internet means thread problem, that is, thread conflict, and I don't know which one to execute. The specific statement is as follows:

There are three kinds of threading models provided by COM: Single-Threaded Apartment (STA single-threaded suite), Multithreaded Apartment (MTA multithreaded suite) and Neutral Apartment/Thread Neutral Apartment/Neutral Threaded Apartment (NA/TNA/NTA neutral threading suite, provided by COM +).

One object of STA can only be accessed by one thread, which is equivalent to the message loop of windows, and the implementation mode is also through the message loop. ActiveX controls, OLE document servers and other interfaces all use STA suites. MTA 1 object can be accessed by multiple threads, that is, the code of this object implements thread protection in its own methods, which ensures that it can change its own state correctly.

Therefore, when creating and accessing an activex or ole object, you must set the thread mode to sta.

So, how do you use OpenFileDialog in child threads so that you don't continue to report such errors? Here is the changed code:


/// <summary>
    ///  Single-threaded open excel Document 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnXlx_Click(object sender, EventArgs e)
    {
      this.textBox1.Text = string.Empty;

      System.Threading.Thread s = new System.Threading.Thread(new System.Threading.ThreadStart(getExcel));
      s.ApartmentState = System.Threading.ApartmentState.STA;
      s.Start();

    }

    /// <summary>
    ///  Read excel Document address 
    /// </summary>
    private void getExcel()
    {
      OpenFileDialog ofd = new OpenFileDialog();
      ofd.Filter = "Microsoft Office Excel(*.xls;*.xlsx)|*.xls;*.xlsx";
      ofd.FilterIndex = 1;
      ofd.RestoreDirectory = true;


      if (ofd.ShowDialog() == DialogResult.OK)
      {
        // Detect whether the open file path is an empty address 
        if (!string.IsNullOrEmpty(ofd.FileName))
        {
          ReadFromExcelFile(ofd.FileName);
        }
        else
        {
          this.textBox1.Text = " Please open excel Documents ";
        }
      }
    }

It is to separate the contents of thread execution into a method, and then write a single-thread execution statement to execute sub-threads in the event. In this case, the error of thread exception will not be reported.

PS: By searching online content, individuals can sum up and feel a solution. Add [STAThread] to the front door of other functions such as Main, and there are other 1 methods, which have not solved the problem. The personal method may seem troublesome to the Great God. If the Great God has a better method, then 10 thanks and welcome to share here!


Related articles: