Domanda

Voglio sapere qual è il modo migliore per elaborare i risultati di un processo a lungo in esecuzione in serie, ma su un thread a bassa priorità utilizzando il . NET 4.0 le estensioni parallele .

Ho il seguente classe che sia fa l'esecuzione e fornisce i risultati:

public class Step 
{
  public string Name { get; set; }
  public TimeSpan Duration { get; set; }
  public bool Completed { get; set; }

  public void Execute() 
  {
     DateTime before = DateTime.Now;
     RemotedService.DoSomeStuff();
     Duration = DateTime.Now - before;
     Completed = true;
  }
}

Come posso elaborare questi passi e anche salvarli in un file, in ordine, dopo che sono stati elaborati? Vorrei salvarli in un file mentre RemotedService.DoSomeStuff() è in attesa di una risposta dal server.

La scrittura il file sarebbe come questo:

using (StreamWriter w = File.AppendText("myFile.txt"))
{
  var completedStep = completedSteps.Dequeue();
  w.WriteLine(string.Format("Completed {0} with result: {1} and duration {2}", 
                            completedStep.Name, 
                            completedStep.Completed, 
                            completedStep.Duration));
}

Una possibilità che viene in mente è quello di aggiungere a un Queue e hanno un Timer che i processi di loro. Ma questo non sfruttare i tempi morti delle chiamate comandate a distanza.

Un'altra opzione che viene in mente è quello di scrivere in modo asincrono ogni risultato per il file utilizzando un System.Threading.Tasks.Task per Step, ma che non garantisce che verranno salvati in ordine e possono anche introdurre contesa con la scrittura al file.

È stato utile?

Soluzione

Vorrei suggerire la creazione di un BlockingCollection<Step> (vedi System.Collections.Concurrent namespace). Come ogni fase è stata completata, è sommato a quello di raccolta. Il comportamento predefinito di BlockingCollection è quello di funzionare come una coda, in modo otterrete il comportamento FIFO che stai cercando.

Un secondo filo servizi della coda, la rimozione di ogni elemento e la scrittura in un file di log.

Quindi, se si aggiunge la coda:

static private BlockingCollection<Step> LogQueue = new BlockingCollection<Step>();

Si dovrebbe aggiungere questo al tuo metodo di Execute, dopo che l'oggetto è stato completato:

LogQueue.Add(this);

E il tuo thread di registrazione, che si dovrebbe iniziare nel costruttore statico:

static void LoggingThread()
{
    using (var w = new StreamWriter(...))
    {
        while (!LogQueue.IsCompleted())
        {
            Step item;
            if (LogQueue.TryTake(out item))
            {
                w.WriteLine(....);
            }
        }
    }
}

Il filo di registrazione, come ho scritto che utilizza un filo System.Threading. Ci potrebbe essere un modo più semplice, o meglio farlo con TPL. Non ne sono ancora terribilmente familiarità con TPL, quindi non ho potuto dire.

Altri suggerimenti

Un approccio è quello di creare un costume Utilità di pianificazione (vedi http: // msdn .microsoft.com / en-us / library / ee789351.aspx ). La vostra abitudine task scheduler può limitare la concorrenza a one-at-a-tempo e far rispettare rigorosa esecuzione in-order.

La creazione di un programmatore di operazione permette anche di controllare la priorità del thread, o l'ApartmentState che può essere desiderabile in alcune situazioni.

Si sta letteralmente descrivendo il caso d'uso per il Workflow Foundation - Lo fa tutte queste cose per voi:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top