2011-08-27 13 views
9

Jestem nowy w C#, ale zrobiłem dużo java. Oto mój problem: Próbuję otworzyć "SaveFileDialog" z wątku, który nie jest wątkiem interfejsu użytkownika.C#: Pokaż okno dialogowe na wątku UI z innego wątku

To jest dokładnie to, co staram się robić:

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

Metoda ta zawsze będzie wywoływana z wątku innego niż ten, który jest właścicielem formularza. Problem polega na tym, że gdy wykonuję ten kod, "Form1" zamarza, a "SaveFileDialog" nie pojawia się.

Czy masz jakąś wskazówkę, która pomoże mi wyświetlić dialog z niezależnego wątku?

Odpowiedz

6

Spróbuj tego:

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

Nie działa: "AskSaveFile" musi zwrócić ciąg znaków. A jeśli czekam na wynik z "EndInvoke", mam ten sam problem ("Form1", zamrożenie). – Moinonime

+0

Pierwsza część nowego kodu powoduje, że Dialog jest wykonywany w głównym wątku ... więc to może działać .... O, tak, główny wątek to wykona ... ale czy masz na myśli, że twój główny wątek robi coś innego i nie może być użyty ? Uwierzcie mi, używam tego kodu w różnych wątkach w moich aplikacjach i działa ... więc musi być coś, czego nie rozumiem teraz ... – Marco

+0

Pytanie: twoje wątki to wątki lub BackgroundWorkers? – Marco

11

Zrób to wyglądać tak:

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

Jeśli nadal się impas następnie należy użyć okna Debug + Windows + Nici debugger i patrzeć na to, co Wątek interfejsu użytkownika działa. Funkcja Control.Invoke() nie może zostać ukończona, chyba że wątek interfejsu użytkownika jest bezczynny i pompuje pętlę komunikatów. Oczekiwanie na zakończenie wątku roboczego zawsze spowoduje zakleszczenie.

Należy również wziąć pod uwagę, że ten rodzaj kodu jest ryzykowny, użytkownik może nie oczekiwać, że to okno dialogowe pojawi się nagle i przypadkowo je zamknąć podczas pisania lub pisania na klawiaturze w oknach należących do wątku interfejsu użytkownika.

Powiązane problemy