在下面的代码中,我有一个名为GetExcelData
的长时间运行过程。完成后,我想显示一个对话框,将其内容保存到TXT文件中。
问题是,在调试时,我收到以下错误:
当前线程必须设置为单线程单元(STA)模式 在进行OLE调用之前。确保您的主要功能 STAThreadAttribute标记在上面。只有在a时才会引发此异常 调试器附加到进程。
这是我的代码。该错误发生在读取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项目中存在以下内容,该项目引用了我的控制台项目:
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);
}
}
}
答案 0 :(得分:1)
将与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事件中检索它。
答案 1 :(得分:1)
基本上,您从saveFileDialog1.ShowDialog();
致电bw_DoWork
。这不对。 Dialog
是UI控件,应该从UI线程运行,bw_DoWork
方法在单独的线程(非UI)中执行。
将对话框显示代码移离bw_DoWork
方法,然后传递所需的字符串。所以算法看起来像
答案 2 :(得分:0)
修改您的Program.cs
,以便Main
方法的声明如下所示:
[STAThread]
static void Main()