Multithreading

domenica 08 giugno 2008 - 11.12

maxmax03 Profilo | Newbie

Ciao , sto diventando matto con un problema di mulltithreading.
Da una dll mi arriva la notifica dell'evento di cambiamento di stato di un servizio.
La routine che a cui arriva l'evento deve visualizzare su un TreeView lo stato dei servizi. Ma qui ho il problema si freeza la window e sul VS 2008 cosi come sul vs 2005 mi dice che devo utilizzare INVOKE o beginInvoke.
Mi potreste far capire come funziona con un esempio. Non ho capito molto bene sulle ricerce fatte su internet.
Grazie

freeteo Profilo | Guru

ciao,
se vuoi fare una cosa veloce senza troppi problemi, prova ad usare questa direttiva nel form load:
Control.CheckForIllegalCrossThreadCalls = false;
così eviti che ti compaia l'errore quando un thread diverso da quello che ha creato la form va ad interagire con i controlli.
Non è il massimo dell'eleganza, ma cmq è efficace.

ciao.

Matteo Raumer
[MCAD .net]
http://blogs.dotnethell.it/freeteo

maxmax03 Profilo | Newbie

Ti ringrazio ma già provato e non da il risultato che voglio. IL problema che non riesco ha capire e che sto cercando disperatamente è come un thread principale (form) ricece un evento da una dll. Dall'evento devo aggiornare una treeview ma i dati devo reperili da un metodo che è presente nella dll che scatena l'evento. Comunque garzie

freeteo Profilo | Guru

>Ti ringrazio ma già provato e non da il risultato che voglio.
non si aggiorna la treeview con i valori che hai?
Forse allora il problema è qualcos'altro.


>IL problema che non riesco ha capire e che sto cercando disperatamente
>è come un thread principale (form) ricece un evento da una dll.
>Dall'evento devo aggiornare una treeview ma i dati devo reperili
>da un metodo che è presente nella dll che scatena l'evento. Comunque
la cosa è abbastanza semplice da fare, prova a postare 1po di codice su come ti sottoscrivi all'evento e come hai definito l'evento.
Grazie

ciao.

Matteo Raumer
[MCAD .net]
http://blogs.dotnethell.it/freeteo

maxmax03 Profilo | Newbie

using ExeQry = Siae.Tools.ExecuteQry ;
using System;
using System.Windows.Forms;
using System.ServiceProcess ;
using System.Threading ;
namespace ClientService
{

public delegate void ChangeEventHandler(object source,int Stato);


public class PCSService
{
//private ServiceController myService = new ServiceController("System Control Service");
private Thread THService;
public event ChangeEventHandler Changed;
private delegate void IncPBDelegate();


private bool mvarThreadService = false;
private string mvarStrStatus = "" ;
private int mvarStatus = 99;
private TreeView mvarObjView= null;
private ImageList mvarObjImg= null;
/// <summary>
/// Return the service status
/// </summary>
public int Status
{
get{return mvarStatus;}
set{mvarStatus = value;}
}
/// <summary>
/// Return the service status
/// </summary>
public string DescStatus
{
get{return mvarStrStatus;}
set{mvarStrStatus = value;}
}
/// <summary>
/// Set o retrun the threadstatus for check the service
/// </summary>
public bool ThreadService
{
get{return mvarThreadService;}
set{mvarThreadService = value;}
}
public TreeView ObjView
{
get{return mvarObjView;}
set{mvarObjView = value;}
}
public ImageList ObjImg
{
get{return mvarObjImg;}
set{mvarObjImg = value;}
}
/// <summary>
///
/// </summary>
public PCSService()
{

}
/// <summary>
/// Start the thread for check service
/// </summary>
public void StartCheckService()
{
if (THService != null)
{
if (THService.IsAlive == false)
{
CreateThread();
}
else{mvarThreadService = false;}
}
else{CreateThread();}
}

/// <summary>
/// notifica la modifica dello stato
/// </summary>
protected void CreateThread()
{
mvarThreadService = true;
THService = new Thread(new ThreadStart(ServiceStatus));
THService.Name = "ServiceStatus";
THService.Start();
}

public void ChangedStatus(int Stato)
{
if (Changed != null)
Changed(this,mvarStatus);
}

public void ServiceStatus()
{

while (mvarThreadService==true)
{
ServiceController myService = new ServiceController("System Control Service");
Type MyStatoString = typeof(ServiceControllerStatus);

if (myService != null)
{
// Servizio Arrestato
if (myService.Status.Equals(System.ServiceProcess.ServiceControllerStatus.Stopped))
{
if (mvarStatus !=(Convert.ToInt16(ServiceControllerStatus.Stopped)))
{
mvarStrStatus = Enum.GetName(MyStatoString,ServiceControllerStatus.Stopped ) ;
mvarStatus = Convert.ToInt16(ServiceControllerStatus.Stopped);
ChangedStatus(Convert.ToInt16(ServiceControllerStatus.Stopped));
}
}
// Servizio Attivo
if (myService.Status.Equals(System.ServiceProcess.ServiceControllerStatus.Running))
{
if (mvarStatus != (Convert.ToInt16(ServiceControllerStatus.Running)))
{
mvarStrStatus = Enum.GetName(MyStatoString,ServiceControllerStatus.Running) ;
mvarStatus = Convert.ToInt16(ServiceControllerStatus.Running);
ChangedStatus(Convert.ToInt16(ServiceControllerStatus.Running));
}
}
// In Pausa
if (myService.Status.Equals(System.ServiceProcess.ServiceControllerStatus.Paused))
{
if (mvarStatus != (Convert.ToInt16(ServiceControllerStatus.Paused)))
{
mvarStrStatus = Enum.GetName(MyStatoString,ServiceControllerStatus.Paused) ;
mvarStatus = Convert.ToInt16(ServiceControllerStatus.Paused);
ChangedStatus(Convert.ToInt16(ServiceControllerStatus.Paused));
}
}
}
myService.Dispose();
Thread.Sleep(60000);
}
}

public void ViewStatus()
{

TreeNode tNode= new TreeNode();
ExeQry.Application ObjExecQry = new ExeQry.Application();
//mvarObjView.BeginUpdate();
mvarObjView.ImageList = mvarObjImg;
mvarObjView.ImageIndex = 5;
mvarObjView.SelectedImageIndex = 5;
mvarObjView.Nodes.Add(new TreeNode("attvio"));
//'ObjView.Nodes.Add(tNode)
//mvarObjView.EndUpdate();
ObjExecQry.XMLFileName = @"C:\temp\TempFileXml.XML";
ObjExecQry.TreeViewView =mvarObjView;
ObjExecQry.Type_View = Siae.Tools.ExecuteQry.Application.Enum_Type_View.TreeView;
ObjExecQry.ViewData.ImgList = mvarObjImg;
ObjExecQry.ViewData.set_PIconNumber(0,14);
ObjExecQry.ViewData.set_SIconNumber(0,14);
ObjExecQry.ViewData.set_PIconNumber(1,5);
ObjExecQry.ViewData.set_SIconNumber(1,5);
ObjExecQry.ViewData.set_PIconNumber(2,15);
ObjExecQry.ViewData.set_SIconNumber(2,1);
//'ExeQry.ViewData.ModeView = View.Details
ObjExecQry.ViewData.NameFirstNode ="Servizi";
ObjExecQry.ViewData.set_FieldIndex(0, "Monitor");
//ObjExecQry.ViewData.set_FieldIndex(1, "Servizio");
ObjExecQry.ViewQuary();

ObjExecQry = null;
}

}
}

---------------------------------------- parte VB.net
' Private Delegate Sub ChgTreeView()


Private Sub objs_AnEvents(ByVal source As Object, ByVal Stato As Integer) Handles PCSObjS.Changed
Call pippo()
End Sub
Sub pippo()

']If Me.InvokeRequired() Then
'Me.Invoke(New ChgTreeView(AddressOf pippo))
'End If

Control.CheckForIllegalCrossThreadCalls = False
Dim tNode As TreeNode = New TreeNode()
Dim ObjExecQry As ExecuteQry.Application = New ExecuteQry.Application()
Me.trvService.BeginUpdate()
Me.trvService.ImageList = Me.ImageListS
Me.trvService.ImageIndex = 5
Me.trvService.SelectedImageIndex = 5
Me.trvService.Nodes.Add(New TreeNode("attvio"))
Control.CheckForIllegalCrossThreadCalls = True



End Sub

Ecco il questo è il codice sia di C# che di vb
chiaramente la parte vb è implemtata per fare una prova. ho provato anche con il delegate
ti ringrazio

freeteo Profilo | Guru

il codice mi sembra corretto, se debugghi, ti passa per l'evento "objs_AnEvents" e ti va in errore?
Potrebbe essere un problema che si scatenano tanti eventi in rapida successione? In questo caso devi lavorare con il "lock" oppure dando al metodo che chiami l'attributo " [MethodImpl(MethodImplOptions.Synchronized)] " in modo che sia eseguito atomicamente...

Eventualmente puoi provare con "SuspendLayout() e ResumeLayout()" prima di aggiungere i nodi alla treeview per evitare l'appesantimento della parte grafica del controllo...

ciao.

Matteo Raumer
[MCAD .net]
http://blogs.dotnethell.it/freeteo

maxmax03 Profilo | Newbie

ho provato anche con il nuovo controllo BackgroundWorker ma ottengo sempre lo stesso risultato. Non capisco per quale motivo non si riescono ad aggiornare i controllo su un thread separato dal principale. Sto verificando ancora su internet se ci fosse qualcuno che ha avtuo lo stesso problema
Se ti venisse in mente qualche altra soluzione suggeriscimela
grazie comunque

maxmax03 Profilo | Newbie

Mi sono dimenticato di dirti che l'evento funziona correttamente e che dal in cui creco di impostare il treeview va in errore

freeteo Profilo | Guru

ciao,
guarda come procedimento deve funzionare,l'ho usato decine di volte, e lo stesso vale per il backgrroundWorker.
Ma qual'è l'errore dettagliato? è di cross-thread?

ciao.

Matteo Raumer
[MCAD .net]
http://blogs.dotnethell.it/freeteo

maxmax03 Profilo | Newbie

Si esatto Operazione cross-thread non valida
HO RISOLTO GRAZIE PER L'AIUTO
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-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5