Thread problem

  • Thread starter Thread starter Víctor
  • Start date Start date
V

Víctor

Hello,

I'm filling a array of System.Diagnostic.Process by using GetProcesses()
method. Due to a retard on this method, I do the call using a function and
it passing like a delegate to one thread. I've defined the array like
private at class level, but when thread terminates, array is void (I've
checked that array isn't void before thread delegate terminate).

Can somebody help me? I believed that by declaring vars like private in a
class, I could access they even from a thread and these vars could keep
value to use after.

Thanks.Víctor
 
Hi,

Can you post some code?
I don't see why you need a separate method just for this, you get an array
of process just by calling GetProcesses


cheers,
 
Yes, I know, but I want draw in a kind of taskbar only processes which
Handle is different to IntPtr.Zero (with Window) and I need store processes
info in a Process Array to read each element after and draw a button if
element value isn't Zero. The problem occurs when I tried get element
information and array was void after finish thread.

Thanks again.
 
Víctor said:
Yes, I know, but I want draw in a kind of taskbar only processes which
Handle is different to IntPtr.Zero (with Window) and I need store processes
info in a Process Array to read each element after and draw a button if
element value isn't Zero. The problem occurs when I tried get element
information and array was void after finish thread.

As Ignacio said before, please post some code. It's impossible to guess
what the problem is just from the description.
 
Víctor said:
In code below, there are the function which act as delegate and calling
function. You can see, in Form1_Load, that I create a object called frmTBar,
the class definition is in attach file TaskBar.cs. Code for
ProcessOperations (compiled as dll and referenced on application), is
comprissed into processOperations.rar.

That's all a bit of a pain to look at, to be honest. Could you shorten
it to a short but complete program which demonstrates the problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
Víctor said:
In code below, there are the function which act as delegate and calling
function. You can see, in Form1_Load, that I create a object called
frmTBar,
the class definition is in attach file TaskBar.cs. Code for
ProcessOperations (compiled as dll and referenced on application), is
comprissed into processOperations.rar.

private TaskBar frmTBar; //TaskBar Form

private ProcessOperations.SystemProcess cProc; //Reference to class in dll

private void Form1_Load(object sender, System.EventArgs e)

{

frmTBar=new TaskBar(this);

frmTBar.Dock=DockStyle.Bottom;

frmTBar.Show();

this.cProc= new ProcessOperations.SystemProcess();


System.Threading.Thread t=new System.Threading.Thread(new
System.Threading.ThreadStart(leeProcesos));

t.IsBackground=true;

t.Start();

}

private void leeProcesos()

{

string pName;

int pHandle;

this.cProc.leeProcesosVentana();

for(int i=0;i<this.cProc.ProcesosVentana;i++)

{

pName=cProc.obtenNombreProcesoVentana(i);

pHandle=cProc.obtenHandleProcesoVentana(i);

frmTBar.addProcess(pHandle,pName);

}

}

Thank you very much.


Didn't look into this in detail, but I noticed that you are updating the UI
from another thread than the UI thread; Here you call frmTBar.addProcess


frmTBar.addProcess(pHandle,pName);

and in addProcess you update the UI, this is a big NO NO in windows.

IMO this part of the code wasn't designed to be multithreaded (and IMO
shouln't be) from the start, you changed existing code to run an existing
method on another thread and hoped evrything would be ok. Well, it isn't
that simple, when updating UI elements from another thread than the UI
thread, you need to marshal the calls, check Invoke and BeginInvoke in the
Control class and http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
for details.


Willy.
 
Hi,

I've proved with a smaller application and I've verified that I tried get
collection values before thread terminates, then collection was void. I've
been looking into Willy link example and I believe that this is the
solution. Code with my tests is at code below (if somebody has same problem
can see it). When I find solution I'll tell you (or for new problems :-( ).

Thank you.

Paste code in a Windows Form Project
using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Threading;

namespace PruebaThread

{

/// <summary>

/// Descripción breve de Form1.

/// </summary>

public class Form1 : System.Windows.Forms.Form

{

/// <summary>

/// Variable del diseñador requerida.

/// </summary>

private System.ComponentModel.Container components = null;

public System.Diagnostics.Process[] listaProc;

public Coleccion listaProcVentana=new Coleccion();

public Form1()

{

//

// Necesario para admitir el Diseñador de Windows Forms

//

InitializeComponent();

//

// TODO: agregar código de constructor después de llamar a
InitializeComponent

//

}

/// <summary>

/// Limpiar los recursos que se estén utilizando.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

listaProc=null;

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Código generado por el Diseñador de Windows Forms

/// <summary>

/// Método necesario para admitir el Diseñador. No se puede modificar

/// el contenido del método con el editor de código.

/// </summary>

private void InitializeComponent()

{

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(616, 273);

this.Name = "Form1";

this.Text = "Form1";

this.Load += new System.EventHandler(this.Form1_Load);

}

#endregion

/// <summary>

/// Punto de entrada principal de la aplicación.

/// </summary>

[STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void Form1_Load(object sender, System.EventArgs e)

{

Thread t=new Thread(new ThreadStart(leeProcesosVentana));

t.Start();

MessageBox.Show("Thread out: " + listaProcVentana.Count.ToString());

}





public void leeProcesos()

{

listaProc=System.Diagnostics.Process.GetProcesses();

}

public void leeProcesosVentana()

{

leeProcesos();

foreach(System.Diagnostics.Process p in listaProc)

if(p.MainWindowHandle!=IntPtr.Zero)

if(!listaProcVentana.Contains(p)) listaProcVentana.Add(p);

MessageBox.Show("Thread in: " + listaProcVentana.Count.ToString());

}

}

public class Coleccion: CollectionBase

{

public object this[int indice]

{

get

{

return ((object)List[indice]);

}

set

{

List[indice]=value;

}

}

public int Add(object value)

{

return List.Add(value);

}


public int IndexOf(object value)

{

return( List.IndexOf( value ) );

}

public void Insert( int index, object value )

{

List.Insert( index, value );

}

public void Remove( object value )

{

List.Remove( value );

}

public bool Contains(object value )

{

// If value is not of type Int16, this will return false.

return( List.Contains( value ) );

}

protected override void OnInsert( int index, object value )

{

if (value==null)

throw new ArgumentException( "No se admiten valores nulos.", "value" );

}

protected override void OnRemove( int index, object value )

{

if (value==null)

throw new ArgumentException( "No se admiten valores nulos.", "value" );

}

protected override void OnSet( int index, object oldValue, object newValue )

{

if (newValue==null)

throw new ArgumentException( "No se admiten valores nulos.", "newValue" );

}

protected override void OnValidate( object value )

{

if (value==null)

throw new ArgumentException( "No se admiten valores nulos.", "value" );

}

}

}
 
Víctor said:
Hi,

I've proved with a smaller application and I've verified that I tried get
collection values before thread terminates, then collection was void. I've
been looking into Willy link example and I believe that this is the
solution. Code with my tests is at code below (if somebody has same
problem
can see it). When I find solution I'll tell you (or for new problems
:-( ).

If you do this:

Thread t=new Thread(new ThreadStart(leeProcesosVentana));
t.Start();
MessageBox.Show("Thread out: " + listaProcVentana.Count.ToString());

..... MessageBox.Show execute before the thread has even started so your
listaProcVentana.Count will be 0.
You have to wait until the thread procedure has finished before you can read
the value of listaProcVentana.Count

t.Start();
// Do other stuff here while your thread procedure runs
....
// Use Thread.Join to wait for the thread to finish
t.Join()
// Use value of listaProcVentana.Count here.

Willy.
 
Back
Top