在下面的代码中,我有一个名为GetExcelData的长期运行的过程。完成后,我想显示一个对话框,将其内容保存到TXT文件中。

问题是,在调试时,出现以下错误:


  当前线程必须设置为单线程单元(STA)模式
  才能进行OLE调用。确保您的Main函数具有
  STAThreadAttribute标记在上面。仅在以下情况下引发此异常:
  调试器已附加到该进程。


这是我的代码。错误出现在读取saveFileDialog1.ShowDialog();的行上

FileInfo existingFile = new FileInfo("C:\\MyExcelFile.xlsx");

ConsoleApplication2.Program.ExcelData data = ConsoleApplication2.Program.GetExcelData(existingFile, _worker);

var json = new JavaScriptSerializer().Serialize(data);

SaveFileDialog saveFileDialog1 = new SaveFileDialog();

saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
saveFileDialog1.ShowDialog();

if (saveFileDialog1.FileName != "")
{
    File.WriteAllText(saveFileDialog1.FileName, json);
}


我尝试将[STAThread]属性添加到我从中调用的方法中,但是它似乎没有用。

请让我提供更多代码,以进一步明确我要执行的操作:

WPF项目中存在以下内容,该项目引用了我的Console项目:

private BackgroundWorker _backgroundWorker = new BackgroundWorker();

public MainWindow()
{
    InitializeComponent();

    // Set up the BackgroundWorker.
    this._backgroundWorker.WorkerReportsProgress = true;
    this._backgroundWorker.WorkerSupportsCancellation = true;
    this._backgroundWorker.DoWork += new DoWorkEventHandler(bw_DoWork);
    this._backgroundWorker.ProgressChanged +=
                              new ProgressChangedEventHandler(bw_ProgressChanged);
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (this._backgroundWorker.IsBusy == false)
    {
        this._backgroundWorker.RunWorkerAsync();
    }
    e.Handled = true;
}

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Set the Value porperty when porgress changed.
    this.progressBar1.Value = (double)e.ProgressPercentage;
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker _worker = sender as BackgroundWorker;
    if (_worker != null)
    {
        FileInfo existingFile = new FileInfo("C:\\MyExcelFile.xlsx");

        ConsoleApplication2.Program.ExcelData data = ConsoleApplication2.Program.GetExcelData(existingFile, _worker);

        var json = new JavaScriptSerializer().Serialize(data);

        SaveFileDialog saveFileDialog1 = new SaveFileDialog();

        saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
        saveFileDialog1.ShowDialog();

        if (saveFileDialog1.FileName != "")
        {
            File.WriteAllText(saveFileDialog1.FileName, json);
        }
    }
}

最佳答案

将与UI交互的代码移动到处理UI元素的相同线程。通过RunWorkerCompleted事件实现此目的的最简单方法

  this._backgroundWorker.RunWorkerCompleted +=
                          new RunWorkerCompletedEventHandler(bw_WorkComplete);

  ....

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker _worker = sender as BackgroundWorker;
    if (_worker != null)
    {
        FileInfo existingFile = new FileInfo("C:\\MyExcelFile.xlsx");
        ConsoleApplication2.Program.ExcelData data = ConsoleApplication2.Program.GetExcelData(existingFile, _worker);

        e.Result = new JavaScriptSerializer().Serialize(data);
     }
 }

 private void bw_WorkComplete(object sender, RunWorkerCompletedEventArgs e)
 {
    SaveFileDialog saveFileDialog1 = new SaveFileDialog();
    saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
    saveFileDialog1.ShowDialog();

    if (saveFileDialog1.FileName != "")
    {
       string json = e.Result.ToString();
       File.WriteAllText(saveFileDialog1.FileName, json);
    }
}


在DoWork方法中,将json字符串保存在DoWorkEventArgs类的e.Result属性中,然后从具有相同名称的RunWorkerCOmpletedEventArgs属性的RunWorkerCompleted事件中检索它。

07-27 21:56