简体   繁体   中英

SaveFileDialog doesn't show in new thread?

I've been confused by this problem for a very long time. I start the new thread by using System.Threading, just like this:

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

and

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();
}

But the dialog won't show and it seems that the thread will abort immediately when executing "ShowDialog". Is this a bug or I made a mistake? Can a background thread shows a savefile dialog?

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

The thread you created doesn't establish a message loop, so you cannot show it.

Better is to ask user the file path on the UI thread and then start your export thread, passing it the file name. Still better is using a BackgroundWorker thread so that your UI remains responsive.

Update: If you cannot use BackgroundWorker, below is the code for the alternative I described. I assume you have a method similar to ExportDataTableToFile which you call after you get the file name.

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

And I assume you're on the UI thread here:

//
// 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();

try this

in your class

private object sync_temp = new object();

and in thread method

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;
}

or mark that thread as STAThread

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM