2013-04-10 2 views
5

Ho cercato quasi ovunque su internet e ho cercato su Google così tante volte e ho trovato così tanti risultati, ma non riesco ancora a trovare la soluzione al mio problema.Come si usa Dispatcher.BeginInvoke correttamente?

Sono occupato nella conversione di una vecchia applicazione WinForms in una nuova applicazione WPF, ma ho problemi con alcuni comandi. Nell'applicazione Winforms usano Control.BeginInvoke() e lo memorizzano in un oggetto IAsyncResult. Ho letto che il Dispatcher.BeginInvoke() è la WPF equivalente al Control.BeginInvoke() per WinForms ma ottengo questo errore quando uso

Dispatcher.BeginInvoke(): "Impossibile convertire implicitamente il tipo 'System.Windows.Threading.DispatcherOperation' a 'System.IAsyncResult'. Esiste una conversione esplicita (ti manca un cast?) ".

Qualsiasi aiuto sarà apprezzato.

Ecco il codice che sto cercando di convertire. Questo è il codice originale WinForms. Sono in grado di convertire tutto tranne la parte BeginInvoke.

private eSkan.api.TeSkanAPI feSkanAPI = null; 

    private void MessageFilter_AddRemove_Invoked(bool AddFilter, IMessageFilter Filter) 
    { 
     if (AddFilter){ Application.AddMessageFilter(Filter); } 
     else { Application.RemoveMessageFilter(Filter); } 
    } 

    private void MessageFilter_AddRemove(bool AddFilter, IMessageFilter Filter) 
    { 
     { 
      IAsyncResult sr = BeginInvoke((ESKAN_ADD_REMOVE_MESSAGEFILTER)MessageFilter_AddRemove_Invoked, 
              AddFilter, Filter); 
      sr.AsyncWaitHandle.WaitOne(2000); 
     } 
    } 

Qui di seguito è il mio codice che ho convertito finora compresa la parte BeginInvoke che sto lottando con.

private void MessageFilter_AddRemove_Invoked(bool addFilter, System.Windows.Forms.IMessageFilter filter) 
    { 
     if (addFilter) 
     { 
      System.Windows.Forms.Application.AddMessageFilter(filter); 
     } 
     else 
     { 
      System.Windows.Forms.Application.RemoveMessageFilter(filter); 
     } 
    } 

    private void MessageFilter_AddRemove(bool addFilter, System.Windows.Forms.IMessageFilter filter) 
    { 
     { 
      IAsyncResult sr = System.Windows.Threading.Dispatcher.BeginInvoke((ESKAN_ADD_REMOVE_MESSAGEFILTER)MessageFilter_AddRemove_Invoked, addFilter, filter); 
      sr.AsyncWaitHandle.WaitOne(2000); 
     } 
    } 

Se ci sono altri errori, per favore fatemelo sapere.

Grazie

+2

Puoi pubblicare il codice che stai cercando di convertire? Sembra che tu stia utilizzando il valore restituito di 'Control.BeginInvoke' nell'originale ma, senza vedere come, è difficile commentare la modifica appropriata. –

+0

La risposta di Michael è buona, ma vale anche la pena notare che la riga 'sr.AsyncWaitHandle.WaitOne (2000)' mette semplicemente in pausa il thread corrente per 2 secondi, e sembrerebbe ridondante (almeno, io * spero * sia ridondante ...). Se si rimuove questa riga, non è necessario il valore restituito (solo la richiamata). –

+0

Sì, la risposta di Michael è buona, ma ho ancora problemi con una piccola parte. Devo usare un'API personalizzata per il callback. Questa è la parte in cui assegnano BeginInvoke() all'oggetto IAsyncResult. Ho provato alcuni modi per ottenere il codice giusto in modo che possa svolgere la sua funzione, ma sto lottando per farlo bene. – GANDA1F

risposta

4

Questo perché Dispatcher.BeginInvoke, anche se può essere l'operazione logica equivalente, non restituisce un IAsyncResult, restituisce un DispatcherOperation. Dai uno sguardo a this blog post e vedrai un buon esempio di come funziona lo Dispatcher. Ho copiato qui l'esempio di codice pertinente per assicurarmi che esista più tardi.

public Window1() 
{ 
    InitializeComponent(); 

    CheckBox myCheckBox = new CheckBox(); 
    myCheckBox.Content = "A Checkbox"; 

    System.Threading.Thread thread = new System.Threading.Thread(
    new System.Threading.ThreadStart(
     delegate() 
     { 
     System.Windows.Threading.DispatcherOperation 
      dispatcherOp = myCheckBox.Dispatcher.BeginInvoke(
      System.Windows.Threading.DispatcherPriority.Normal, 
      new Action(
      delegate() 
      { 
       myCheckBox.IsChecked = true; 
      } 
     )); 

     dispatcherOp.Completed += new EventHandler(dispatcherOp_Completed); 
     } 
)); 

    thread.Start(); 
} 

void dispatcherOp_Completed(object sender, EventArgs e) 
{ 
    Console.WriteLine("The checkbox has finished being updated!"); 
} 

Prendere nota di questa linea:

dispatcherOp.Completed += new EventHandler(dispatcherOp_Completed); 

è così che si sta andando a sapere quando è completato - è andare a chiamare di nuovo voi via quell'evento.

+0

Grazie mille per la tua risposta Michael. I tuoi lavori grandi grazie. – GANDA1F

+0

Vorrei solo aiutarmi con un'altra cosa. Quello è che ho bisogno di passare due diverse variabili a una funzione che sto chiamando. Si prega di vedere il mio codice sopra se non chiaro. – GANDA1F