2011-08-27 123 views
9

我是C#的新手,但是我做了很多java。這是我的問題:我試圖從不是UI線程的線程打開「SaveFileDialog」。C#:在另一個線程的UI線程上顯示對話框

這正是我試圖做的事:

public partial class Form1: Form 
{ 
    public string AskSaveFile() 
    { 
     var sfd = new SaveFileDialog(); 
     sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"; 
     sfd.FilterIndex = 1; 
     sfd.RestoreDirectory = true; 
     DialogResult result = (DialogResult) Invoke(new Action(() => sfd.ShowDialog(this))); 
     if(result == DialogResult.OK) 
     { 
      return sfd.FileName; 
     } 

     return null; 
    } 
} 

這種方法將總是從誰擁有該表的一個不同的線程調用。問題是,當我執行此代碼時,「Form1」凍結和「SaveFileDialog」不顯示。

你有什麼線索可以幫助我從一個獨立的線程顯示對話框嗎?

回答

6

試試這個:

public partial class Form1: Form 
{ 
    public string AskSaveFile() 
    { 
     if (this.InvokeRequired) 
     { 
      Invoke(new MethodInvoker(delegate() { AskSaveFile(); })); 
     } 
     else 
     { 
      var sfd = new SaveFileDialog(); 
      sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"; 
      sfd.FilterIndex = 1; 
      sfd.RestoreDirectory = true; 
      if(sfd.ShowDialog() == DialogResult.OK) return sfd.FileName; 
     }    
     return null; 
    } 
} 
+0

不工作:「AskSaveFile」需要返回一個字符串。如果我等待「EndInvoke」的結果,我得到了同樣的問題(「Form1」凍結)。 – Moinonime

+0

新代碼的第一部分使對話框在主線程中執行...所以這可以工作....哦,是的,主線程將執行此..但你的意思是你的主線程是做一些不同的,不能使用?相信我,我在我的應用程序的不同線程中使用此代碼,它的工作原理...所以一定有一些我現在不明白的東西... – Marco

+0

一個問題:你的線程是線程或BackgroundWorkers? – Marco

11

使它看起來像這樣:

public string AskSaveFile() { 
     if (this.InvokeRequired) { 
      return (string)Invoke(new Func<string>(() => AskSaveFile())); 
     } 
     else { 
      var sfd = new SaveFileDialog(); 
      sfd.Filter = "Fichiers txt (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"; 
      sfd.FilterIndex = 1; 
      sfd.RestoreDirectory = true; 
      return sfd.ShowDialog() == DialogResult.OK ? sfd.FileName : null; 
     } 
    } 

如果你仍然得到那麼僵局,一定要使用調試器的調試+的Windows +線程窗口,看看是什麼UI線程正在做。除非UI線程空閒並且抽取消息循環,否則Control.Invoke()無法完成。等待工作線程完成總是會導致死鎖。

還要考慮到這種代碼是有風險的,用戶可能不希望這個對話框在UI線程擁有的窗口中鼠標或鍵盤輸入時突然出現並意外關閉它。