2011-08-27 4 views
9

저는 C#을 처음 접했지만 많은 자바 작업을 수행했습니다. 여기에 내 문제가 : 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

새 코드의 첫 번째 부분은 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; 
     } 
    } 

당신은 여전히 ​​교착 상태가 다음 디버거의 디버그 + 윈도우 + 스레드 창을 사용해야하고 무엇을 볼 수있는 경우 UI 스레드가 수행 중입니다. UI 스레드가 유휴 상태이고 메시지 루프를 펌핑하지 않으면 Control.Invoke()를 완료 할 수 없습니다. 작업자 스레드가 끝날 때까지 기다리는 것은 항상 교착 상태를 일으킬 수 있습니다.

또한이 종류의 코드는 위험합니다. 사용자가 UI 대화 상자가 소유 한 창에서 마우스를 움직이거나 키 보드하는 동안이 대화 상자가 갑자기 나타나고 우연히 닫히지 않을 수도 있습니다.