2011-08-27 21 views
9

Sono nuovo di C#, ma ho fatto un sacco di java. Ecco il mio problema: sto cercando di aprire un "SaveFileDialog" da un thread che non è il thread dell'interfaccia utente.C#: mostra la finestra di dialogo sul thread dell'interfaccia utente da un altro thread

Questo è esattamente quello che cerco di fare:

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

Questo metodo sarà sempre essere chiamato da un thread diverso da quello che possiede il modulo. Il problema è che quando eseguo questo codice, il blocco "Form1" e il "SaveFileDialog" non vengono visualizzati.

Avete qualche idea per aiutarmi a mostrare il dialogo da un thread indipendente?

risposta

6

Prova questo:

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

Non funziona: "AskSaveFile" deve restituire una stringa. E se aspetto il risultato con "EndInvoke" ho avuto lo stesso problema (congelamento "Form1"). – Moinonime

+0

La prima parte del nuovo codice rende la finestra di dialogo eseguita nel thread principale ... quindi potrebbe funzionare ... Oh, sì, il thread principale verrà eseguito .. ma intendi che il thread principale sta facendo qualcosa di diverso e non può essere usato ? Credimi, uso questo codice in diversi thread nelle mie app e funziona ... quindi deve esserci qualcosa che non capisco adesso ... – Marco

+0

Una domanda: i tuoi thread sono Thread o BackgroundWorkers? – Marco

11

farlo sembrare come questo:

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

Se viene ancora stallo quindi assicurarsi di utilizzare la finestra di debug + Windows + Fili del debugger e guardare a ciò che il Il thread dell'interfaccia utente sta facendo. Control.Invoke() non può essere completato a meno che il thread dell'interfaccia utente sia inattivo e non pompi il loop dei messaggi. Aspettare che finisca il thread di lavoro causerà sempre un deadlock.

Considerate anche che questo tipo di codice è rischioso, l'utente potrebbe non aspettarsi che questa finestra di dialogo venga visualizzata improvvisamente e chiusa accidentalmente durante il mouse o la tastiera nelle finestre di proprietà del thread dell'interfaccia utente.

Problemi correlati