Multitasking in C #

1

Vorrei usare un timer nel mio programma C # con una precisione milliseconda per mantenere una fotocamera sincronizzata con alcuni eventi e continuare a scattare una foto ogni 250ms (o 1/4 di secondo, oppure potrei regolarla anche a tempi più brevi come 200ms o 100ms). Per questo può essere usato il normale evento del timer.

Ma mi chiedo quale sarebbe il modo migliore per farlo.

Inoltre, penso che NON dovrei scrivere l'intera routine di cattura, ma alza semplicemente un altro thread (multi-threading) per elaborare l'immagine con una logica di visione su di esso, poiché la mia logica di visione impiega circa 1 secondo, quindi otterrà qualche coda qui.

Se i miei algoritmi di visione impiegherebbero 1 secondo per thread, ciò significherebbe che su un PC multicore (12 core) tale thread di codice passerebbe al successivo processore libero disponibile o sto pensando facilmente al multitasking?

    
posta user613326 13.01.2013 - 16:54
fonte

2 risposte

2

Voglio aggiungere un altro punto alla risposta già buona di Danny Varod , incentrata sulla domanda nel tuo ultimo paragrafo .

Supponendo che tu gestisca gli eventi generati dal timer multimediale o da un altro timer ad alta risoluzione, ora devi inviare la tua pesante attività di elaborazione in un'altra discussione. Le librerie di .NET rendono questo relativamente facile usando la libreria Task Parallelism (TPL) se stai usando .NET 4.0, o usando direttamente il ThreadPool per le versioni precedenti.

Diciamo che hai questo codice (molto abbozzato):

private void ProcessImage(object imageToProcess)
{
    // Do whatever. Process the image, save the results, etc.
    // This is the 1-sec process.
}

private void myTimer_Elapsed()
{
    Image capturedImage = myCamera.CaptureImage(); // or whatever.
    Task.Factory.StartNew(ProcessImage, capturedImage);
}

Questo avvia una nuova attività (un wrapper attorno a un metodo asincrono) che viene avviata su un thread ThreadPool. Se la tua macchina ha più CPU e più core, il ThreadPool avrà molti thread disponibili e elaborerà molte di queste richieste in parallelo. Si spera che ciò consentirà alle attività di elaborazione di tenere il passo con le attività di acquisizione delle immagini. Potrebbe essere necessario leggere il threadpool e vedere come modificare i thread disponibili per le macchine con molte CPU, ma lo scenario peggiore è che le attività di elaborazione vengano ripristinate, ma il threadpool (che è il cuore della libreria di attività ) li accosteranno e li raggiungeranno alla fine.

Nota, comunque, che sei non garantito che le attività saranno eseguite nell'ordine in cui sono state acquisite.

Se utilizzi una versione precedente di C #, sostituisci la chiamata a Task.Factory.StartNew con le chiamate a ThreadPool.QueueUserWorkItem , che in questo caso (dove non stiamo utilizzando le continuazioni e la gestione aggregata degli errori) sarà praticamente identica utilizzo.

    
risposta data 13.01.2013 - 21:49
fonte
2
  1. Utilizza il Timer multimediale . Funziona bene anche con intervalli di 10 mS (e forse meno).

  2. Quando si verifica l'evento timer, potrebbe essere necessario inviare al thread principale (o un altro thread singolo), a seconda che l'API della fotocamera e l'API di elaborazione delle immagini supportino l'accesso da più thread. Utilizza la classe di Dispatcher per questo.

  3. Assicurati che il tuo gestore di eventi sia più corto dell'intervallo del timer, quando si verifica l'evento del timer, controlla se il gestore di eventi è occupato e in tal caso decidi cosa fare (ad es. ignora l'evento).

  4. Decidi cosa fare con le immagini, o crea una nuova immagine ad ogni evento (sconsigliato a causa del costo del GC), o riutilizzare il buffer delle immagini purché le dimensioni dell'immagine e la profondità del colore non siano cambiate. Si consiglia di creare un'immagine di output per ogni fase del processo di elaborazione delle immagini, per abilitare il rivestimento delle tubature per l'elaborazione delle immagini e per consentire all'elaborazione delle immagini di modificare la dimensione dell'immagine / la profondità del colore. Se l'API per l'elaborazione delle immagini supporta il multithreading, dovrai assicurarti di non utilizzare contemporaneamente lo stesso buffer di immagini (ad esempio utilizzando la sincronizzazione pipeline o utilizzando immagini diverse per ciascun evento).

Se la tua elaborazione richiede ~ 1 sec, allora ti ritroverai con una coda crescente di immagini (o quantità di thread) perché non sarai in grado di tenere il passo. Se non si riesce ad attendere molto tempo perché l'elaborazione termini dopo l'acquisizione, sarà necessario ridefinire il codice di elaborazione dell'immagine. Prova a spostarlo sulla GPU (usando GPGPU).

    
risposta data 13.01.2013 - 17:32
fonte

Leggi altre domande sui tag