MultiThread (take 2)

mercoledì 19 gennaio 2011 - 11.04
Tag Elenco Tags  C#  |  VB.NET  |  .NET 3.0  |  Windows 7  |  Windows Vista  |  Windows XP  |  Visual Studio 2008

ale091970 Profilo | Newbie

Buongiorno.
Ci riprovo, visto che la precedente richiesta non ha avuto fortuna.

Ho scritto in .net una dll che, per farla breve:
- riceve in input un file di testo
- lo legge per intero e quando trova righe contenenti dati interessanti, li estrae e li salva su un db temporaneo
- al termine della lettura del file elabora i dati salvati sul db
- infine riespone le elaborazioni su Excel

Ho poi realizzato una semplice windows form in c#, come interfaccia per l'utente, che utilizza la dll suddetta.

Tutto il processo impegna il computer qualche minuto, in funzione delle dimensioni del file originale e delle prestazioni del pc: durante questo tempo il form d'interfaccia risulta ovviamente bloccato.
La soluzione per ovviare a questo problema è lanciare l'elaborazione del file in un nuovo thread, corretto? Partendo dal presupposto che sono totalmente ignorante in materia di multi-thread, ci sono aspetti rilevanti che è bene che io sappia prima di far danni?

E soprattutto: come faccio a fare in modo che, durante l'elaborazione, la dll lanci dei "messaggi" sull'avanzamento del lavoro? I messaggi dovrebbero essere intercettabili dalla form (o comunque da qualsiasi programma che utilizzi la dll in un thread separato) in modo che possa mostrare all'utente il progresso (o anche aggiornare i log)?!

Grazie
Alessandro

luigidibiasi Profilo | Guru

>sono aspetti rilevanti che è bene che io sappia prima di far
>danni?
in .net sicuramente non fai danni

>
>E soprattutto: come faccio a fare in modo che, durante l'elaborazione,
>la dll lanci dei "messaggi" sull'avanzamento del lavoro?
puoi utilizzare i [delegate], i methodinvoker oppure gli eventi...

>I messaggi
>dovrebbero essere intercettabili dalla form (o comunque da qualsiasi
>programma che utilizzi la dll in un thread separato) in modo
>che possa mostrare all'utente il progresso (o anche aggiornare
>i log)?!

permetti alla dll di accettare registrazioni da parte di chi la utilizza...
appena ho vb sotto mano cerco di scrivere un esempio...

>
>Grazie
>Alessandro

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

ale091970 Profilo | Newbie

Grazie per la pronta risposta, Luigi.
Perdonami se approfitto della tua competenza, ma avrei bisogno di qualche dettaglio in più.

>>E soprattutto: come faccio a fare in modo che, durante l'elaborazione,
>>la dll lanci dei "messaggi" sull'avanzamento del lavoro?
>puoi utilizzare i [delegate], i methodinvoker oppure gli eventi...

Hai mica qualche link da consigliarmi, possibilmente con esempi?


>>I messaggi
>>dovrebbero essere intercettabili dalla form (o comunque da qualsiasi
>>programma che utilizzi la dll in un thread separato) in modo
>>che possa mostrare all'utente il progresso (o anche aggiornare
>>i log)?!
>
>permetti alla dll di accettare registrazioni da parte di chi
>la utilizza...
>appena ho vb sotto mano cerco di scrivere un esempio...
>

Ecco, qui per me parli arabo...
Aspetto l'esempio.

Grazie mille
Alessandro

luigidibiasi Profilo | Guru

Si scusami ho scritto in modo confusionario...

ho allegato al post un esempio di multithreading con la callback... nel codice ho messo i commenti per descrivere cosa avviene...

Ho usato VB ma se devi usare C# la conversione è immediata...

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

ale091970 Profilo | Newbie

Grazie, molto gentile.
Guardo il tuo esempio e ne faccio tesoro; eventualmente tornerò a disturbarti nuovamente.

Grazie ancora.
Alessandro

ale091970 Profilo | Newbie

Buongiorno Luigi.
Torno a disturbarti perché mi sono incagliato con il codice che mi hai dato; non riesco a tradurre la parte che riguarda il form in c#.

Ho scritto questo:

private delegate void HandlerXThread(string stepstatus);
private Delegate _InvokeMeOnStep = new HandlerXThread(_HandlerXThread);

public void _HandlerXThread (string stepstatus)
{
lblAttesa.Text = stepstatus;
}


Ma quando compilo ricevo il seguente errore (relativo alla seconda linea):
"A field initializer cannot reference the non-static field, method, or property 'frmMain._HandlerXThread(string)'"

Grazie ancora.
Alessandro

luigidibiasi Profilo | Guru

Si, infatti in c# la sintassi è un po' diversa...

ho scritto un esempio di codice in una form con una sola label, tuttavia sono un po' arruginito con c# quindi la chiamata al delegato sono riuscito a farla sono passandogli gli argomenti in quel modo astruso che vedi...

dopo se riesco la correggo

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private static int kkk=0; private delegate void HandlerXThread(Object o); public static void _HandlerXThread(Object o) { String x = (String)((System.Collections.ArrayList)o)[0]; ((Label)((System.Collections.ArrayList)o)[1]).Text = kkk.ToString(); } private HandlerXThread del = _HandlerXThread; private void _aTh(Object o) { while(true) { kkk += 1; this.Invoke(del,o); } } private void Form1_Load(object sender, EventArgs e) { System.Collections.ArrayList a; System.Threading.Thread th; System.Threading.ParameterizedThreadStart ths; ths = new System.Threading.ParameterizedThreadStart(_aTh); th = new System.Threading.Thread(ths); a = new System.Collections.ArrayList(); a.Add(""); a.Add((object) lbl); th.Start(a); } } }
Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

luigidibiasi Profilo | Guru

ecco vedi così se fa al caso tuo

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

ale091970 Profilo | Newbie

Perdonami Luigi, ma non sono sicuro sia quello che mi serve; quest'ultimo form in c# non mi pare utilizzi la dll in vb che hai scritto per il primo esempio, corretto?
perché la mia situazione è proprio questa: form in c# e dll in vb che fa il lavoro lungo.

Grazie ancora dell'aiuto, buona serata
Alessandro

luigidibiasi Profilo | Guru

si perdonami ho messo solo il codice per il delegato
puoi allegare il progetto che ho messo la scorsa volta perché non riesco a scaricarlo e non lo tengo più :)

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

ale091970 Profilo | Newbie

Eccolo!

http://www.dotnethell.it/users/files/1552_1537_esempiomultithreadconcallback.zip

Grazie ancora per il prezioso aiuto, buona giornata.

Alessandro

luigidibiasi Profilo | Guru

vedi un po' così
Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/

ale091970 Profilo | Newbie

Fantastico, grazie mille per il prezioso aiuto!!!
Posso farti due ulteriori richieste in tema, per favore?

1 - Al termine dell'esecuzione della routine nella dll (EseguiThread) il nuovo thread viene automaticamente chiuso, liberando le risorse?
Te lo chiedo perché mi è capitato che il form andasse in errore perché non riusciva a eliminare un file ancora in uso presumibilmente dalla dll, che però aveva già finito l'esecuzione.

2 - Esiste un modo per interrompere l'esecuzione della routine (e quindi del thread), usando ad esempio un bottone sul form??

Grazie mille ancora, buona giornata.

luigidibiasi Profilo | Guru

>Fantastico, grazie mille per il prezioso aiuto!!!
>Posso farti due ulteriori richieste in tema, per favore?
>
>1 - Al termine dell'esecuzione della routine nella dll (EseguiThread)
>il nuovo thread viene automaticamente chiuso, liberando le risorse?
dato che abbiamo usato tutti oggetti gestiti dovrebbe occuparsene il garbace collection.
magari lancia un gc.collect ;)


>Te lo chiedo perché mi è capitato che il form andasse in errore
>perché non riusciva a eliminare un file ancora in uso presumibilmente
>dalla dll, che però aveva già finito l'esecuzione.

no, in questo caso devi liberare il file. c'è un altro problema devi debuggare

>
>2 - Esiste un modo per interrompere l'esecuzione della routine
>(e quindi del thread), usando ad esempio un bottone sul form??

si, ipotizziamo che il thread si chiami th lanci th.abort

>
>Grazie mille ancora, buona giornata.

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5