在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常
最近用C#搞一个项目,用到了openFileDialog,出现了如题这个问题,后来各种百度各种谷歌,找到了问题的根源。在MSDN中有描述:
单元是进程内部具有相同线程访问要求的对象的逻辑容器。同一单元中的所有对象都可以接收从该单元中的任何线程发出的调用。.NET Framework 不使用单元,托管对象自己负责以线程安全的方式使用所有共享资源。由于 COM 类使用单元,因此公共语言运行库需要在 COM interop 的情况下调用 COM 对象时创建并初始化一个单元。托管线程可以创建并进入只允许有一个线程的单线程单元 (STA) 或者包含一个或多个线程的多线程单元 (MTA)。通过将线程的 ApartmentState 属性设置为 ApartmentState 枚举值之一,可以控制所创建的单元的类型。由于给定线程只能初始化 COM 单元一次,因此在第一次调用非托管代码之后就不能更改单元类型。
例如:
private void back_Click(object sender, EventArgs e)
{
Thread td = new Thread(delegate() { call(ref db, ref state,ref filename,ref length); });
td.SetApartmentState(ApartmentState.STA);
td.Start();
///其他处理
}
public void call(ref double[] db,ref int state,ref string name,ref int length)
{
this.openFileDialog1.Filter = "文本文件(*.txt)|*.txt";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
name = openFileDialog1.FileName;
FileStream fs = new FileStream(name, FileMode.Open);
BinaryReader br = new BinaryReader(fs);
try
{
while ((db[length] = br.ReadDouble()) != 0) ///判断文件结尾,如果到了结尾了就会出错,进入catch部分
{
length++;
}
}
catch
{
///MessageBox.Show("到文件结尾了!!!");
}
br.Close();
fs.Close();
state = 1; ///表示点击了确定
return;
}
state = 2; ///表示点击了取消
}