Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13

Discussione: threads e eventi

  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    threads e eventi

    ciao.
    Ho creato un sistema di notifiche push con il webservice di exchange ma potrebbe essere qualsiasi altro webservice.
    In pratica ho un metodo che risponde ad un evento quando faccio un cambiamento su exchange.
    Il problema è che posso avere molti eventi e su ognuno di questi devo svolgere un "lavoro" cioè fare 2 3 cose e inserire un dato in 2 3 tabelle .
    mi chiedevo se fare partire un thread o un task o una funzione asincrona che crea una nuova connessione e inserisce tutto su db.
    non sapendo quasi nulla del multitasking chiedo qui.
    grazie.

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2015
    Messaggi
    57
    I thread gli usi se vuoi che effettivamente qualcosa sia fatto in un processo parallelo o concorrente,
    sono comunque ad un livello basso d'esecuzione.

    Piuttosto che i thread generalmente conviene usare i Task, che ti definiscono solo che la risposta o l'esecuzione di un determinata azione verrà data in un futuro più o meno prossimo, il vantaggio dei Task è che vengono gestiti da un pool.

    L'uso delle parole await/async è un metodo semplificato per gestire la tecnologia Task più vicina agli aspetti sequenziali dell'utente, i quali possono essere anche semplicemente in un contesto di sincronizzazione differente.

    Pertanto nel tuo esempio conviene senza dubbio usare i Task con await/async, tenendo sempre in considerazione i limiti definiti dal pc client e quelli dati dal servizio web, prestando sempre molta attenzione agli aspetti critici della programmazione asincrona.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    Quote Originariamente inviata da Marsh Visualizza il messaggio
    I thread gli usi se vuoi che effettivamente qualcosa sia fatto in un processo parallelo o concorrente,
    sono comunque ad un livello basso d'esecuzione.

    Piuttosto che i thread generalmente conviene usare i Task, che ti definiscono solo che la risposta o l'esecuzione di un determinata azione verrà data in un futuro più o meno prossimo, il vantaggio dei Task è che vengono gestiti da un pool.

    L'uso delle parole await/async è un metodo semplificato per gestire la tecnologia Task più vicina agli aspetti sequenziali dell'utente, i quali possono essere anche semplicemente in un contesto di sincronizzazione differente.

    Pertanto nel tuo esempio conviene senza dubbio usare i Task con await/async, tenendo sempre in considerazione i limiti definiti dal pc client e quelli dati dal servizio web, prestando sempre molta attenzione agli aspetti critici della programmazione asincrona.

    grazie , molto gentile , in particolare io ho due thread da lanciare uno ogni tot di tempo e uno invece
    che vada sempre(gli eventi ) tranne quando va il thread di sopra.
    Gli eventi possono essere molti e devo aspettare che tutti siano finiti preima di lanciare il thread principale.E' per questo che hai parlato di pool?
    posso usare await per gestire la cosa come si usa ?
    perchè tutti e due i thread(i thread degli eventi possono essere molti ma unificati in un unico pool) lavorano su una risorsa condivisa e possono nascere problemi se lavorano tutti e due insieme.
    Inoltre sto documentandomi sulla cosa e ho visto che un problema classico dei thread è che se tutti e due aspettano la fine dell altro il programma si pianta.
    scusa se sono poco preparato sull argomento.
    inoltre se mi puoi dare un link da cui partire per i task te ne sarei grato.
    ciao.
    grazie.

    ps. lo so che ci vuole dell esperienza ad usare il multitasking ma se non inizio non l'avro mai.
    Ultima modifica di giuseppe500; 02-02-2016 a 11:35

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    allora ho visto un po su google.
    ricapitolando ho molti task che reagiscono e partono di risposta ad eventi.
    Posso lanciare una funzione asincrona e farmi restituire in qualche modo un id o qualcosa del genere da mettere in una lista per sapere quando sto per lanciare l'altro task se tutti i task degli eventi sono completati se no aspettare?
    e fare la stessa cosa per gli eventi? vedere se il task dell importazione generale è conclso e allora mandare in esecuzione i task degli eventi?
    le paroline sono asynk e await ma come usarle è un po criptico per me.
    inoltre ho visto che tutti i task ritornano un dato di solito una stringa o un oggetto generic e non quel famigerato id che vorrei come posso procedere ?
    Si possono creare pool di task?.
    grazie.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2015
    Messaggi
    57
    premetto che non ho capito esattamente le tue intenzioni,
    però mi sembra di vedere un po' di confusione

    solitamente sarei d'accordo con te nel provare in pratica le metodologie per capire
    ma quando si parla di multitasking un po' di teoria è fondamentale.

    Quando tu crei un Thread dividi il tuo processo in più sotto-processi, questo significa che con un nuovo Thread il tuo programma possiederà il Thread principale più quello che hai creato tu, quindi avrai due sotto-processi.

    Se il sistema in cui gira la tua applicazione dovesse avere un unico core, significherebbe che i tuoi due Thread che concorrono verranno eseguiti a pezzi uno dopo l'altro per dare l'impressione che stia facendo due operazioni insieme anche se in realtà non è così.

    Mentre se il tuo sistema ha più core, ad ogni core disponibile verrà assegnato un Thread nel limite del possibile eseguendo realmente una linea concorrenziale/parallela d'esecuzione.

    Il problema è che generare un Thread è un operazione costosa, considera che vengono dedicati dei registri ed uno stack d'esecuzione, pertanto se porti ad avere un accumulo vai in overhead, cioè sprechi risorse, quindi la ricerca del parallelismo e delle performance ti portano ad avere un esecuzione ancora più lenta di un processo sincrono.

    A questo scopo entra in gioco il Thread-Pool, sostanzialmente a lui dai una serie di azioni da eseguire il quale si occuperà di creare i Threads e di eseguirne quanti più possibile concorde al dato processore, se vi saranno più azioni verranno messe in coda, così da limitare anche i context-switch del sistema operativo, inoltre riutilizzano Thread già usati per limitare al minimo l'overhead citato precedentemente.

    Il problema principale del Multithread sono le risorse condivise, come detto precedentemente possiedono una propria memoria, inoltre possiedono una memoria condivisa fra i vari sottoprogrammi, questo significa che se le tue risorse sono condivisibili o mutabili inizierai a soffrire di problemi noti come Race Conditions, ad esempio le più comuni come: check-then-act oppure read-modify-write, in poche parole significa che i tuoi processi eseguono azioni su dati che in quel momento potrebbero non essere più coerenti per colpa di un altro processo che ha cambiato le carte in tavola.

    Questi sono problemi che ad ogni esecuzione possono presentarsi, come non verificarsi quasi mai, pertanto devi assicurarti di avere creato un programma al 100% Thread-safe.

    Per risolvere questi generi di problemi hai un sacco di soluzioni,
    lock
    https://msdn.microsoft.com/it-it/library/c5kehkcz.aspx
    semafori (barrier)
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
    mutex
    https://msdn.microsoft.com/en-us/lib...ing.mutex.aspx
    monitor
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx
    per problemi legati a visibilità hai volatile
    https://msdn.microsoft.com/it-it/library/x13ttww7.aspx

    ed altri ancora,
    puoi anche affidarti a tecniche di protezione tua, come confinamento a stack, confidamento a thread, tecniche di immutabilità, molti leggono ma uno solo scrive, e cosi via.

    Per fortuna, puoi evitare tutto questo utilizzando i "Tasks", sono anch'essi thread, quello che girà dietro è esattamente quello definito fino ad ora però da programmatore ti danno dei vantaggi, in primo caso non soffri più di problemi di condivisione, essendo che utilizzano in modo automatico delle barriere per proteggere le risorse, inoltre i "Task" quando gli istanzi vengono in automatico aggiunti ad uno specifico "Pool di Task", che ti garantisce l'esecuzione più performante per il dato processore.

    In entrambi i casi, ammettendo che usi i Thread (puri) e quindi gestisci per bene tutte le procedure di sincronizzazione e protezione dei dati oppure i "Tasks", come hai citato precedentemente, devi stare attento a problemi che non riguardando un esecuzione inconsistente, ma bensì impediscono al programma di progredire nel lavoro.

    Deadlock: quando un thread blocca una risorsa per sempre, pertanto un altro thread non può più avervi accesso, quindi il tuo programma rimarrà bloccato per sempre.
    Starvation: quando ad un thread viene negata per sempre la possibilità di essere eseguito, ad esempio un thread ha priorità maggiore ed esegue sempre lui la sua azione negando agli altri la possibilità di essere processati.
    Livelock: Al contrario del Deadlock il processo continua ad eseguire un azione fallendola, in seguito ci ritenta, quindi è sempre in esecuzione ma blocca le funzioni degli altri.

    Queste genere di problematiche le puoi evitare solo con una buona se non ottima progettazione.

  6. #6
    Utente di HTML.it
    Registrato dal
    Jul 2015
    Messaggi
    57
    dato che i "Tasks" ci semplificano le cose, conviene senza dubbio puntare su di loro,
    di per se non hanno nulla di particolare
    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx

    ammettiamo che tu abbia una banale funzione sincrona
    quando premi il pulsante esegui un metodo

    codice:
            private int m_Count = 0;
    
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                this.SyncAction(10);
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString(); // out: 135
            m_Count = 0;
            }
    
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private void SyncAction(int n)
            {
                for (int i = 0; i < n; i++)
                {
                    Thread.Sleep(100);
                    m_Count += i * 3;
                }
            }
    però il metodo risulta lento, a causa della moltitudine di operazioni da effettuare pertanto questa azione porta al blocco dell'applicativo (il classico "non risponde" quando cerchi di interagire), questo perché l'unico Thread è quello del Main, il quale controllo anche i componenti grafici.

    per ovviare a questa problematica puoi utilizzare un "Task", questo porta la tua azione ad essere gestita in modo asincrono.
    ora sappiamo che la nostra variabile condivisa m_Count grazie all'utilizzo dei "Task" rimane protetta, però devi stare comunque attento alla condivisione dei componenti grafici.

    ATTENZIONE QUESTA PARTE È DI PROPOSITO SBAGLIATA.
    codice:
            private int m_Count = 0;
    
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                Task.Run(() => this.AsyncAction(10));
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString(); // out: 0 ~ 18 ~ 9 ~ 135 ~ ...
            m_Count = 0;
            }
    
            /// <summary>
            /// Metodo asincrono controllato dal Task
            /// </summary>
            private void AsyncAction(int n)
            {
                for (int i = 0; i < n; i++)
                {
                    Thread.Sleep(100);
                    m_Count += i * 3;
                }
            }
    abbiamo generato un problema di sincronizzazione, questo perché il Thread Main continua il suo percorso, e in concorrenza il Task esegue le proprie azioni, dato che è il sistema operativo che ne decide l'esecuzione non puoi sapere se il Task finirà prima la propria esecuzione rispetto al Thread Main, quindi
    lbText.Text = m_Count.ToString(); // out: 0 ~ 18 ~ 9 ~ 135 ~ ...
    ti da un output sempre differente a seconda di come il sistema operativo gestisce il tutto.

    per ovviare a questo potresti gestire l'output a video direttamente nell'azione del tuo task

    codice:
            /// <summary>
            /// Metodo asincrono controllato dal Task
            /// </summary>
            private void AsyncAction(int n)
            {
                for (int i = 0; i < n; i++)
                    m_Count += this.ExternalAction(i);
    
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                {
                    // stampiamo a schermo
                    lbText.Text = m_Count.ToString(); // out: 135
                    m_Count = 0;
                }));
            }
    i controlli grafici possono essere gestiti solo dal Thread in cui sono stati creati, per tale motivo devi passare attraverso il Dispatcher dell'applicazione per poterli manipolare, il quale rallenta l'esecuzione del Task.

    potresti anche attendere il termine di esecuzione del Task prima di continuare con il Thread Main

    codice:
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                Task t = Task.Run(() => this.AsyncAction(10));
                t.Wait(); // attendiamo il termine del task.
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString(); // out: 135
                m_Count = 0;
            }
    il problema che per aspettare il Task, il Main Thread viene bloccato, quindi torni ad avere il problema della soluzione sincrona.

    per questo genere di problematiche entrano in aiuto le parole chiave ASYNC e AWAIT
    https://msdn.microsoft.com/en-us/library/hh191443.aspx

    Grazie alla parola chiave async, posta nell'intestazione del metodo, definisci che questa procedura verrà eseguita in un contesto di sincronizzazione differente, sempre appartenente al Thread Main, ma non bloccante.

    Tramite la parola await, posta di fronte alla nostra procedura awaitable dettata dal Task, definiamo che necessitiamo di aspettare il termine del Task prima di continuare ad eseguire le nostre azioni nel contesto di sincronizzazione.

    codice:
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread in un contesto differente di sincronizzazione
            /// </summary>
            private async void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                await Task.Run(() => this.AsyncAction(10)); // attende fino al termine della procedura, il ritorno void
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString(); // out: 135
                m_Count = 0;
            }
    Il ritorno dato dal Task dipende dal ritorno della tua funzione asincrona, fino ad ora abbiamo utilizzato un metodo void, ma se non volessimo più appoggiarci ad una variabile condivisa ma lasciare la procedura confinata a thread basta generare un ritorno classico da una funzione, e leggerlo all'uscita del Task, grazie alla parola chiave await, l'esecuzione attenderà il ritorno e quindi l'assegnazione ad m_Count prima di procedere con il resto del metodo.

    codice:
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread in un contesto differente di sincronizzazione
            /// </summary>
            private async void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                m_Count = await Task.Run(() => this.AsyncAction(10)); //  attende fino al termine della procedura, il ritorno int
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString(); // out: 135
                m_Count = 0;
            }
    
            /// <summary>
            /// Metodo asincrono controllato dal Task
            /// </summary>
            private int AsyncAction(int n)
            {
                int count = 0;
                for (int i = 0; i < n; i++)
                {
                    Thread.Sleep(100);
                    count += i * 3;
                }
                return count;
            }
    ricordati che per usare await il metodo deve essere marcato async, e per ottenere i benefici dell'async all'interno del metodo deve esserci una funzione awaitable, in caso contrario l'esecuzione avverrà in modo sincrono.

    Ormai nel framework 4.5 trovi parecchie tra funzioni e metodi che ti richiedono questo genere d'utilizzo, notoriamente lente come DB, web, e così via.

    Se vuoi applicare questo genere di utilizzo sempre, senza far scegliere all'utente se eseguirlo in maniera sincrona o asincrona ti basta eseguire il Task nel metodo specifico, e dare come ritorno "Task<T>", oppure se void "Task".

    codice:
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private async void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                m_Count = await this.AsyncAction(10);
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString();
                m_Count = 0;
            }
    
            /// <summary>
            /// Metodo asincrono controllato dal Main Thread, con all'interno un lambda controllato dal Task
            /// </summary>
            private Task<int> AsyncAction(int n)
            {
                return Task.Run(() => // metodo lambda controllato dal Task
                {
                    int count = 0;
                    int[] results = new int[n];
                    for (int i = 0; i < n; i++)
                    {
                        Thread.Sleep(100);
                        count += i * 3;
                    }
                    return count;
                });
            }
    in questo caso il ritorno è un Task di tipo int, questo significa che applicando la parola await al richiamo ci verrà consegnato al suo termine un risultato futuro di tipo int.

    dato che parlavi di un esecuzione continua, per non intasare eccessivamente il Pool, puoi marcare il tuo Task come LongRunning, questo verrà configurato in modo più appropriato.

    Per questioni di User Experience se un azione dura a lungo, è fondamentale poterla interromperla, per tale motivo puoi definire un Token necessario alla cancellazione del Task.

    codice:
            CancellationTokenSource m_CancellationToken;
    
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private async void ButtonUno_Click(object sender, RoutedEventArgs e)
            {
                m_CancellationToken = new CancellationTokenSource();
                Task<int> task = new Task<int>(
                    () => AsyncAction(10, m_CancellationToken.Token), // azione asincrona
                    m_CancellationToken.Token, // token per la cancellazione
                    TaskCreationOptions.LongRunning); // definiamo un procedimento che durerà parecchio
                task.Start(); // lanciamo il task
                m_Count = await task; // attendiamo il ritorno
    
                // stampiamo a schermo
                lbText.Text = m_Count.ToString();
                m_Count = 0;
            }
    
            /// <summary>
            /// Metodo asincrono controllato dal Task
            /// </summary>
            private int AsyncAction(int n, CancellationToken token)
            {
                int count = 0;
                for (int i = 0; i < n; i++)
                {
                    // se è stata richiesta un interruzione ci fermiamo
                    // e torniamo il risultato calcola solo sino ad ora.
                    if (token.IsCancellationRequested)
                        break;
    
                    Thread.Sleep(1000);
                    count += i * 3;
                }
                return count;
            }
    
            /// <summary>
            /// Metodo sincrono controllato dal Main Thread
            /// </summary>
            private void ButtonDue_Click(object sender, RoutedEventArgs e)
            {
                m_CancellationToken.Cancel(true); // richiediamo l'interruzione.
            }
        }
    Ultima modifica di Marsh; 04-02-2016 a 14:12

  7. #7
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie tante Marsh davvero gentile.
    Ho studiato in questi giorni il tuo codice e gli esempi su google.
    per chiarire quello che ho detto e che devo fare:
    Ho un compito principale che va ogni 15 minuti , ho impostato un threading timer , infatti il tutto sara un servizio.
    e ho un evento che in tempo reale mi invia dei cambiamenti.
    Ora ho creato utilizzando i task come mi hai consigliato e una concorrencyqueque la parte principale.

    I dati dell evento li ho messi con una classe con piu proprieta dato che son 5 in un oggetto e quest oggetto viuene popolato e inserito nella concorrency queque.
    In un loop infinito faccio si di estrarre una per una le classi dati dalla cuncurrency queque e di chiamare una funzione task asincrona, inoltre il trask che mi ritorna la funzione asincrona l'ho messo in una lista di task.
    Il task che parte ogni 15 min aspetta con task.awaitall(listacontask) che tutti i task degli eventi siano completati , a quel momento lancia il task principale(è diventato anch esso un task).
    il problema che volevo evitare era di fare si che la risorsa condivisa in questo caso il db venga toccato da piu di un task, non mi interessa il multicore per adesso era solo per non creare problemi di concorrenza o altri problemi nell accesso al db.
    in questo modo il db è influenzato da un task per volta e se mi arrivano molti eventi vengono immessi nella queque e poi eseguiti quando c'è tempo cosi che non ho un crollo di prestazioni.
    puo andare?
    consigli?
    com è la parte del multicore legata al db se volessi eseguire i task in modo concorrente? è possibile ? uso sql server 12.
    sinceramente sei stato molto disponibile e ti ringrazio se poi vuoi spiegarmi a grandi linee e con link ,non dettagliato come hai fatto per i task ,il muilticore legato al db ti sarei ancora grato.
    ciao.
    e scusa l'ignoranza

  8. #8
    Utente di HTML.it
    Registrato dal
    Jul 2015
    Messaggi
    57
    devo fare una precisazione per quanto riguarda la condivisione delle risorse per i Task che forse come ho scritto potrebbe risultare strano, quando dico che non soffrono di problemi di Race Conditions mi riferisco al loro uso nello stesso contesto di sincronizzazione.

    Infatti la parte di codice riportata sopra con l'errore, oltre ad avere un problema di sincronizzazione con il Main Thread, possiede anche un eventuale problema di condivisione di risorsa, ma questo unicamente se dovesse essere creato un'ulteriore Task in concorrenza che esegue la stessa operazione.

    Nell'esempio seguente utilizzano lo stesso contesto, quindi il tuo risultato sarà sempre corretto, anche se sono 3 azioni che agiscono sullo stesso elemento conteso.

    codice:
         	public static int Count = 0;
    
            public static void Main(string[] args)
            {
                Do();
                Console.ReadLine();
            }
    
            public async static Task Do()
            {
                await Task.Run(() => Action());
                await Task.Run(() => Action());
                await Task.Run(() => Action());
    
                Console.WriteLine(Count);
            }
    
            public static void Action()
            {
                for (int i = 0; i < 100; i++)
                {
                    Count++;
                }
            }
    In quest'altro esempio, invece, viene generata una Race Condition del tipo read-modify-write, infatti i risultati generati dalla variabile condivisa Count sono differenti dai risultati generati dalla variabile condivisa CountVisible che è protetta.

    codice:
     	public static Object Locker = new Object();
            public static int CountVisible = 0;
            public static int Count = 0;
       
            public static void Main(string[] args)
            {
                Do(false);
    
                Console.WriteLine(Count);
                Console.WriteLine(CountVisible);
                Console.ReadLine();
            }
    
            public static void Do(bool p)
            {
                Task t1 = Task.Run(() => Action(p));
                Task t2 = Task.Run(() => Action(p));
                Task t3 = Task.Run(() => Action(p));
    
                Task.WaitAll(new Task[] { t1, t2, t3 });
            }
    
            public static void Action(bool p)
            {
                for (int i = 0; i < 1000000; i++)
                {
                    if (!p)
                    {
                        Count++;
                    }
                    else
                    {
                        // protetta
                        lock (Locker)
                        {
                            CountVisible++;
                        }
                    }
                }
            }
    chiaramente se la tua applicazione è progettata per non possedere risorse contese, quindi con le tecniche di confinamento, non avrai mai problemi del genere.

    la scelta che hai fatto mi sembra buona, se il tuo evento che raccoglie i dati è molto frequente, è senza dubbio meglio mantenerli per un certo periodo localmente ed ogni "tot" tempo sincronizzare il tutto con il DB, questa tecnica viene eseguita da numerose applicazioni.

    la capacità di elaborazione del DB, quindi il numero di connessioni, la velocità di esecuzione e cosi via dipendono dalle impostazioni date al Database le quali sono influenzate dalla macchina su cui risiede, quindi è difficile rispondere alla domanda.

    la cosa importante è che quando esegui la sincronizzazione con il db, effettui una singola connessione per tutti i dati che hai raccolto, ed al termine la chiudi per non occupare lo spazio ad altri eventuali programmi.

    In alternativa all'uso del Timer della sezione Timers o Threading puoi anch'esso eseguirlo con un Task puoi trovare svariati modi per crearlo, il più comune che vedi in giro è il seguente:

    codice:
      	private async Task AsyncIntervalTask(TimeSpan beforeBeginInterval, TimeSpan interval, CancellationToken token)
            {
                if (beforeBeginInterval > TimeSpan.Zero)
                    await Task.Delay(beforeBeginInterval, token);
    
                while (!token.IsCancellationRequested)
                {
                    // azioni da eseguire ogni "interval" di tempo
    
                    //
    
                    if (interval > TimeSpan.Zero)
                        await Task.Delay(interval, token);
                }
            }

  9. #9
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie di tutto

  10. #10
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    ciao Marsh ho un problemino :
    nella gestione degli eventi mi aggiungo i dati e preparo il task e li metto in una queque, il problema è che tu dici di lanciare i task con un timer mi chiedevo se ci sono soluzioni alternative.
    Non posso lanciare tutti i task in maniera asincrona perchè il task 1 immette un id in una tabella e questo id è usato dai task successivi mi chiedevo se esiste una soluzione per far si di lanciare tutti i task in maniera asincrona e aspettare nei task che in successione quando viene inserito l'id si proceda con gli altri task e che gli altri task aspettino prima di procedere che l'id precedente sia inserito e cosi via.
    altrimenti il timer per lanciare i task è indispensabile solo che io adessi blocco l'esecuzione di tutti i task e lancio un task preso dalla queque e riprendo l'esecuzione dei task quando il task che ho lanciato è completato. ma il bloccare l'esecuzione con
    codice:
    System.Threading.Tasks.Task.WaitAll(TaskList.ToArray());
    blocca anche gli eventi e cosi salto alcuni task nel gestore degli eventi e questo è un grosso problema.
    col tuo metodo di lanciare i task ad intervalli regolari tutto ok, ma devo trovare i tempi giusti ed è un po un casino chiedo se posso fare in un altro modo.
    ho anche pensato di passare una lista con tutti i task in esecuzione al task lanciato in modo che quando arriva all' inserimento dell id fa aspettare tutti gli alti task per poi riprenderli alla fine dell' inserimento. puo funzionare? si fa cosi ? chiedo mi piace questo argomento e ti ringrazio in anticipo.
    ciao.
    altro problemino è che i task hanno un ordine di esecuzione che io so , posso risolvere in questo modo?
    alla fine ho due tipi di task: l'inserimento e la cancellazione per l'inserimento posso lanciare tutti i task in maniera asincrona per la cancellazione devo aspettare che gli inserimenti siano finiti forse questo risove
    Ultima modifica di giuseppe500; 22-02-2016 a 10:36

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.