2012-06-28 73 views
1

我一直很困惑這個問題很長一段時間。我使用的System.Threading啓動新的線程,就像這樣:SaveFileDialog不顯示在新線程中?

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」時。這是一個錯誤還是我犯了一個錯誤?後臺線程是否可以顯示保存文件對話框?

+1

您需要調用它,使用調用將允許它顯示GUI線程 –

回答

5

不,對話框必須在UI線程上顯示,就像任何其他UI操作一樣。

+2

。您可以從另一個線程調用MessageBox.Show()。 –

+0

謝謝你的回答。你能告訴我如何在新線程結束時通知UI線程,以便UI線程可以繼續顯示對話框嗎? – wings

+1

@wings:你可以使用'Invoke()'在UI線程上調用函數。或者你可以把你的後臺工作放在一個'BackgroundWorker'中,並在其RunWorkerCompleted委託中顯示對話框。有關這些方法的示例,請參閱文檔。 – ekholm

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(); 
+0

謝謝。但...事實上,我寫的程序更復雜,所以我不得不放棄使用BackgroundWorker.Is有沒有其他方法? – wings

+0

查看我的更新回答。 – henginy

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