SaveFileDialog没有在新线程中显示?

时间:2012-06-28 07:59:34

标签: c# winforms multithreading dialog

很长一段时间以来,我一直对这个问题感到困惑。我使用System.Threading启动新线程,就像这样:

ParameterizedThreadStart threadFileExport = FileExport;
Thread threadExport = new Thread(threadFileExport)
{
    IsBackground = true,
    Name = "threadExport",
    Priority = ThreadPriority.AboveNormal
};
threadExport.Start(_dataTable);

public void FileExport(object objTable)
{

     SaveFileDialog saveFileDialog = new SaveFileDialog
     {
         DefaultExt = "xlsx",
         Filter = "Excel 2007-2010|*.xlsx|" +
                  "Excel95,97,2003|*.xls|",
         FileName = "table.xlsx",
         Title = "Save as. . ."
     };
saveFileDialog.ShowDialog();
}

但是对话框不会显示,似乎线程在执行“ShowDialog”时会立即中止。这是一个错误还是我弄错了?后台线程可以显示保存文件对话框吗?

3 个答案:

答案 0 :(得分:5)

不,必须在UI线程上显示对话框,就像任何其他UI操作一样。

答案 1 :(得分:2)

您创建的主题没有建立消息循环,因此您无法显示它。

最好是询问用户UI线程上的文件路径,然后启动导出线程,并传递文件名。更好的是使用BackgroundWorker线程,以便您的UI保持响应。

<强>更新 如果您不能使用BackgroundWorker,下面是我所描述的替代方案的代码。 我假设您有一个类似于ExportDataTableToFile的方法,您在获得文件名后调用它。

//
// Assuming your actual export method is similar to this:    
//
void ExportDataTableToFile(DataTable dataTable, string fileName) {
    // ...
}

我假设你在这里的UI线程:

//
// You can ask for the file path first;
//
SaveFileDialog saveFileDialog = new SaveFileDialog
{
     DefaultExt = "xlsx",
     Filter = "Excel 2007-2010|*.xlsx|" +
              "Excel95,97,2003|*.xls|",
     FileName = "table.xlsx",
     Title = "Save as. . ."
};
saveFileDialog.ShowDialog();


string fileName = null;
if(saveFileDialog.Result == DialogResult.OK) // "else" case should be added
    fileName = saveFileDialog;

//
// And then start the thread:
//
Thread threadExport = new Thread(() => ExportDataTableToFile(_dataTable, fileName))
{
    IsBackground = true,
    Name = "threadExport",
    Priority = ThreadPriority.AboveNormal
};
threadExport.Start();

答案 2 :(得分:1)

试试这个

你班上的

private object sync_temp = new object();

和线程方法

string path;
SaveFileDialog save = new SaveFileDialog();
// your code to do with "save"
Action ac = () => { lock (sync_temp) { save.ShowDialog(); } };
Invoke(ac);
lock (sync_temp)
{
   path = save.FileName;
}

或将该线程标记为STAThread