2011-08-27 5 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

Not working: "AskSaveFile"は文字列を返す必要があります。そして、私が "EndInvoke"で結果を待つ場合、私は同じ問題( "Form1"フリーズ)を受けます。 – Moinonime

+0

新しいコードの最初の部分は、Dialogがメインスレッドで実行されるようにします...これはうまくいくかもしれません...ああ、はい、メインスレッドはこれを実行します..あなたのメインスレッドは何か違うことをしていて、 ?私のことを信じて、私は私のアプリで別のスレッドでこのコードを使用し、それは動作します...私は今理解していない何かがある必要があります... – 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スレッドが所有するウィンドウでマウス操作やキーボード操作中にこのダイアログが突然表示されたり、誤って閉じたりすることをユーザーが予期しないことがあります。

関連する問題