19

Grazie al buon lavoro di Jeremy Miller in Functional Programming For Everyday .NET Development, ho un executor di comando funzionante che fa tutto ciò che voglio (fare un po 'di fatica sul pool di thread, inviare risultati o errori al contesto di sincronizzazione e persino postare i progressi verso il contesto di sincronizzazione), ma non posso spiegare perché utilizza SynchronizationContext.Send dal pool di thread e Synchronization.Post dal Func passato nel metodo che esegue il sollevamento pesi. Ho letto la documentazione, diverse volte, ma non riesco a capire la differenza. Che cosa dovrei ottenere dal fatto che uno si chiama Send e uno si chiama Post? Sento la magia sta nel fatto Send "inizia una sincrono richiesta " e Post "avvia una richiesta asincrona ", ma entrambe le richieste provengono dal pool di thread e devono essere inviati/pubblicati di nuovo al thread UI.Qual è la differenza tra SynchronizationContext.Send e SynchronizationContext.Post?

Qualcuno può spiegare la differenza, anche se è solo un dispositivo mnemonico che mi consente di sapere quando scegliere l'uno rispetto all'altro?

Nel caso in cui è importante, questo è il mio codice prova dove io uso Post per inviare il progresso di nuovo alla UI:

private Action _ExecuteCommand 
       (SynchronizationContext context 
       , Action<int, int> progress 
       , Action<int, int> after) 
{ 
    int count = 3; 
    int accumulatedValue = 0; 
    int threadId = Thread.CurrentThread.ManagedThreadId; 
    for (int i = 0; i < count; i++) 
    { 
     Thread.Sleep(1000); 
     context.Post(delegate { progress(i + 1, threadId); }); 
     accumulatedValue += i; 
    } 

    return() => after(threadId, accumulatedValue); 
} 

Che _ExecuteCommand metodo viene passato come parametro command di seguito, per lo più dalla Articolo originale, che utilizza per inviare Send completamento e messaggio di errore alla UI:

public void Execute(Func<Action> command, Action<Exception> error) 
{ 
    ThreadPool.QueueUserWorkItem(o => 
    { 
     try 
     { 
      Action continuation = command(); 
      _Context.Send(s => continuation()); 
     } 
     catch (Exception e) 
     { 
      _Context.Send(s => error(e)); 
     } 
    }); 
} 
+4

Sono davvero metodi con nomi errati. –

risposta

23

invia - sincrono: aspettare fo R risposta (o un'azione completata)

Post - asincrono: far scendere e proseguire

Così il vostro esempio utilizza i metodi corretti al momento giusto. Non è necessario interrompere il ciclo for finché non viene completato l'aggiornamento del progresso (al contrario).
E Execute desidera attendere il completamento dell'azione, altrimenti la gestione delle eccezioni non ha alcuno scopo.

+0

Quindi nessun errore si verifica se utilizzo Post anziché Invia. Riguarda se ho bisogno che l'attività del pool di thread si interrompa per inviare/pubblicare il messaggio. Destra? – flipdoubt

+0

Sì, corretto .__ –

+2

Sono ancora confuso da questo. Ho pensato che il contesto di sincronizzazione ti fornisse un modo semplice per lavorare sul thread dell'interfaccia utente, quindi non dovresti aspettarlo? Oppure funziona in questo modo: stai facendo un po 'di lavoro su un thread in background e nel mezzo devi fare un po' di interfaccia utente e poi continuare nel thread in background. Se si utilizza Invia il thread in background non si prosegue fino alla parte 2 fino al termine dell'interfaccia utente, tuttavia se si utilizza il comando Post il thread in background continuerà a funzionare senza attendere il thread dell'interfaccia utente? –

Problemi correlati