Mostrar Form desde otro hilo

26/08/2008 - 22:36 por Ignacio X. Domínguez | Informe spam
Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un icono en la
bandeja y muestra una ventana de notificación cuando ocurre un evento al
estilo messenger y es la clase principal la que maneja el GUI. Tengo además
otra clase con un hilo que cada cierto tiempo llama a un Web Service. Cuando
este servicio devuelve algunos datos la idea es mostrar la ventana de
notificacion. El problema esta en que cuando se llama el metodo que muestra
la ventana la ventana se crea pero no esta visible. Si hago en cambio doble
click sobre el icono (el evento llama al mismo metodo) la ventana se muestra
perfectamente. El problema creo que esta en que la ventana creada desde el
hilo de notificaciones usa el mismo hilo y no el hilo del thread. Intente
solucionarlo con un delegate y un evento, luego llamando al metodo Invoke,
pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano

Preguntas similare

Leer las respuestas

#1 RFOG
27/08/2008 - 10:51 | Informe spam
No he visto tu código en detalle (ya tengo bastante con ver el mío, je
je), pero la forma correcta de tocar código de la UI desde otro hilo
aparte del principal es el de ejecutar ese código desde un método llamado
mediante Invoke.

Luego está el tema de que no te aparece esa ventana. Si lo haces como
arriba seguro que te está apareciendo, lo que ocurre es que al estar el
usuario trabajando con otras, aparece y queda tapada. Para evitarlo,
tienes que poner la propiedad TopMost de la misma a true.

On Tue, 26 Aug 2008 22:36:33 +0200, Ignacio X. Domínguez
wrote:

Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un icono
en la bandeja y muestra una ventana de notificación cuando ocurre un
evento al estilo messenger y es la clase principal la que maneja el
GUI. Tengo además otra clase con un hilo que cada cierto tiempo llama a
un Web Service. Cuando este servicio devuelve algunos datos la idea es
mostrar la ventana de notificacion. El problema esta en que cuando se
llama el metodo que muestra la ventana la ventana se crea pero no esta
visible. Si hago en cambio doble click sobre el icono (el evento llama
al mismo metodo) la ventana se muestra perfectamente. El problema creo
que esta en que la ventana creada desde el hilo de notificaciones usa el
mismo hilo y no el hilo del thread. Intente solucionarlo con un delegate
y un evento, luego llamando al metodo Invoke, pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new
EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano








Microsoft Visual C++ MVP
==Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
Un pintor es un hombre que pinta lo que vende. Un artista, en cambio, es
un hombre que vende lo que pinta.
Respuesta Responder a este mensaje
#2 Ignacio X. Domínguez
27/08/2008 - 16:06 | Informe spam
Ya estoy llamando el metodo a traves de Invoke y la ventana tiene TopMost true. El Invoke lo estoy llamando en un delegate. En el hilo principal no
puedo llamar Invoke porque la clase principal hereda de ApplicationContext
que no tiene ese metodo. La ventana si se esta creando, pero simplemente no
se muestra en pantalla aun minimizando todas las ventanas.

Creo que el problema es el thread en el cual se crea la ventana, y ese es el
problema que no he podido solucionar. Estoy asegurandome que la ventana se
muestre topmost y fuera de foco mediante llamadas a la API de windows de la
siguiente manera:

ShowWindow(Handle, SW_SHOWNOACTIVATE);
SetWindowPos(Handle, (IntPtr)HWND_TOPMOST, this.Left, this.Top, this.Width,
this.Height, SWP_NOACTIVATE);

Funciona perfecto cuando lo llamo desde el hilo de la UI, pero no cuando
llega la notificación.

Gracias


"RFOG" wrote in message news:
No he visto tu código en detalle (ya tengo bastante con ver el mío, je
je), pero la forma correcta de tocar código de la UI desde otro hilo
aparte del principal es el de ejecutar ese código desde un método llamado
mediante Invoke.

Luego está el tema de que no te aparece esa ventana. Si lo haces como
arriba seguro que te está apareciendo, lo que ocurre es que al estar el
usuario trabajando con otras, aparece y queda tapada. Para evitarlo,
tienes que poner la propiedad TopMost de la misma a true.

On Tue, 26 Aug 2008 22:36:33 +0200, Ignacio X. Domínguez
wrote:

Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un icono
en la bandeja y muestra una ventana de notificación cuando ocurre un
evento al estilo messenger y es la clase principal la que maneja el GUI.
Tengo además otra clase con un hilo que cada cierto tiempo llama a un
Web Service. Cuando este servicio devuelve algunos datos la idea es
mostrar la ventana de notificacion. El problema esta en que cuando se
llama el metodo que muestra la ventana la ventana se crea pero no esta
visible. Si hago en cambio doble click sobre el icono (el evento llama
al mismo metodo) la ventana se muestra perfectamente. El problema creo
que esta en que la ventana creada desde el hilo de notificaciones usa el
mismo hilo y no el hilo del thread. Intente solucionarlo con un delegate
y un evento, luego llamando al metodo Invoke, pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new
EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano








Microsoft Visual C++ MVP
==> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio, es
un hombre que vende lo que pinta.
Respuesta Responder a este mensaje
#3 RFOG
27/08/2008 - 17:36 | Informe spam
Pues qué raro. Si pones un breakpoint en el lugar adecuado, ¿se ejecuta el
código que va a mostrar la ventana?

Una chorrada: ¿No tendrá el Visible a false?

On Wed, 27 Aug 2008 16:06:22 +0200, Ignacio X. Domínguez
wrote:

Ya estoy llamando el metodo a traves de Invoke y la ventana tiene
TopMost > true. El Invoke lo estoy llamando en un delegate. En el hilo principal no
puedo llamar Invoke porque la clase principal hereda de
ApplicationContext
que no tiene ese metodo. La ventana si se esta creando, pero simplemente
no
se muestra en pantalla aun minimizando todas las ventanas.

Creo que el problema es el thread en el cual se crea la ventana, y ese
es el
problema que no he podido solucionar. Estoy asegurandome que la ventana
se
muestre topmost y fuera de foco mediante llamadas a la API de windows de
la
siguiente manera:

ShowWindow(Handle, SW_SHOWNOACTIVATE);
SetWindowPos(Handle, (IntPtr)HWND_TOPMOST, this.Left, this.Top,
this.Width,
this.Height, SWP_NOACTIVATE);

Funciona perfecto cuando lo llamo desde el hilo de la UI, pero no cuando
llega la notificación.

Gracias


"RFOG" wrote in message news:
No he visto tu código en detalle (ya tengo bastante con ver el mío, je
je), pero la forma correcta de tocar código de la UI desde otro hilo
aparte del principal es el de ejecutar ese código desde un método
llamado mediante Invoke.

Luego está el tema de que no te aparece esa ventana. Si lo haces como
arriba seguro que te está apareciendo, lo que ocurre es que al estar el
usuario trabajando con otras, aparece y queda tapada. Para evitarlo,
tienes que poner la propiedad TopMost de la misma a true.

On Tue, 26 Aug 2008 22:36:33 +0200, Ignacio X. Domínguez
wrote:

Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un icono
en la bandeja y muestra una ventana de notificación cuando ocurre un
evento al estilo messenger y es la clase principal la que maneja el
GUI. Tengo además otra clase con un hilo que cada cierto tiempo llama
a un Web Service. Cuando este servicio devuelve algunos datos la idea
es mostrar la ventana de notificacion. El problema esta en que cuando
se llama el metodo que muestra la ventana la ventana se crea pero no
esta visible. Si hago en cambio doble click sobre el icono (el evento
llama al mismo metodo) la ventana se muestra perfectamente. El
problema creo que esta en que la ventana creada desde el hilo de
notificaciones usa el mismo hilo y no el hilo del thread. Intente
solucionarlo con un delegate y un evento, luego llamando al metodo
Invoke, pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new
EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano








==>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
>> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio,
es un hombre que vende lo que pinta.








Microsoft Visual C++ MVP
==Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
Un pintor es un hombre que pinta lo que vende. Un artista, en cambio, es
un hombre que vende lo que pinta.
Respuesta Responder a este mensaje
#4 Ignacio X. Domínguez
27/08/2008 - 18:07 | Informe spam
Si, de hecho mando a imprimir por consola el ManagedThreadId cuando la
ventana se muestra y cuando se crea la ventana en el frmNotification_Load y
se llaman bien, lo que quiere decir que efectivamente se crea, pero el
ManagedThreadId cuando la creo en el evento doubleclick del trayicon es
distinto a cuando se crea sola como evento del web service, y en el primer
caso si se muestra... Y en ambos casos se la misma funcion la que se llama..
Realmente no se que hacer..



"RFOG" wrote in message news:
Pues qué raro. Si pones un breakpoint en el lugar adecuado, ¿se ejecuta el
código que va a mostrar la ventana?

Una chorrada: ¿No tendrá el Visible a false?

On Wed, 27 Aug 2008 16:06:22 +0200, Ignacio X. Domínguez
wrote:

Ya estoy llamando el metodo a traves de Invoke y la ventana tiene
TopMost >> true. El Invoke lo estoy llamando en un delegate. En el hilo principal no
puedo llamar Invoke porque la clase principal hereda de
ApplicationContext
que no tiene ese metodo. La ventana si se esta creando, pero simplemente
no
se muestra en pantalla aun minimizando todas las ventanas.

Creo que el problema es el thread en el cual se crea la ventana, y ese
es el
problema que no he podido solucionar. Estoy asegurandome que la ventana
se
muestre topmost y fuera de foco mediante llamadas a la API de windows de
la
siguiente manera:

ShowWindow(Handle, SW_SHOWNOACTIVATE);
SetWindowPos(Handle, (IntPtr)HWND_TOPMOST, this.Left, this.Top,
this.Width,
this.Height, SWP_NOACTIVATE);

Funciona perfecto cuando lo llamo desde el hilo de la UI, pero no cuando
llega la notificación.

Gracias


"RFOG" wrote in message news:
No he visto tu código en detalle (ya tengo bastante con ver el mío, je
je), pero la forma correcta de tocar código de la UI desde otro hilo
aparte del principal es el de ejecutar ese código desde un método
llamado mediante Invoke.

Luego está el tema de que no te aparece esa ventana. Si lo haces como
arriba seguro que te está apareciendo, lo que ocurre es que al estar el
usuario trabajando con otras, aparece y queda tapada. Para evitarlo,
tienes que poner la propiedad TopMost de la misma a true.

On Tue, 26 Aug 2008 22:36:33 +0200, Ignacio X. Domínguez
wrote:

Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un icono
en la bandeja y muestra una ventana de notificación cuando ocurre un
evento al estilo messenger y es la clase principal la que maneja el
GUI. Tengo además otra clase con un hilo que cada cierto tiempo llama
a un Web Service. Cuando este servicio devuelve algunos datos la idea
es mostrar la ventana de notificacion. El problema esta en que cuando
se llama el metodo que muestra la ventana la ventana se crea pero no
esta visible. Si hago en cambio doble click sobre el icono (el evento
llama al mismo metodo) la ventana se muestra perfectamente. El
problema creo que esta en que la ventana creada desde el hilo de
notificaciones usa el mismo hilo y no el hilo del thread. Intente
solucionarlo con un delegate y un evento, luego llamando al metodo
Invoke, pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new
EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano








==>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
>>> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio,
es un hombre que vende lo que pinta.








Microsoft Visual C++ MVP
==> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio, es
un hombre que vende lo que pinta.
Respuesta Responder a este mensaje
#5 RFOG
27/08/2008 - 18:31 | Informe spam
Vaya. Yo tengo por ahí varias aplicaciones con un icono en el tray y
ciertamente se me abren las ventanas al hacer clic, o un menú y desde el
menú la ventana correspondiente...

De todos modos, creo que lo que está mal es esto:

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

¿Estás lanzando el propio evento desde el mismo evento?

Al invoke que yo me refiero es a tener un delegado en el programa
principal que muestre la ventana. Entonces, desde el evento del hilo haces
un invoke de ese delegado, más o menos así:

//Esto está en el hilo principal
public delegate void AbreVentanaDelegate(int param1, int param2);
public void AbreVentana(int param1,int param2)
{
//Mostrar la ventana
}
public AbreVentanaDelegate m_delegado;
public void InvocarAbreVentana(param1,param2)
{
Invoke(m_delegado,param1,param2);
}

//En en constructor de la clase o donde quieras, para que tengas al
"delegado" siempre disponible:
delegado=new MiApp.AbreVentanaDelegate(AbreVentna);

Y luego, desde el hilo, hacer la invocación delegado asignado:

MiApp.InvocarAbreVentana(p1,p2);

Evidentemente el código se puede acortar, pero la idea es esa.


On Wed, 27 Aug 2008 18:07:06 +0200, Ignacio X. Domínguez
wrote:

Si, de hecho mando a imprimir por consola el ManagedThreadId cuando la
ventana se muestra y cuando se crea la ventana en el
frmNotification_Load y se llaman bien, lo que quiere decir que
efectivamente se crea, pero el ManagedThreadId cuando la creo en el
evento doubleclick del trayicon es distinto a cuando se crea sola como
evento del web service, y en el primer caso si se muestra... Y en ambos
casos se la misma funcion la que se llama.. Realmente no se que hacer..



"RFOG" wrote in message news:
Pues qué raro. Si pones un breakpoint en el lugar adecuado, ¿se ejecuta
el código que va a mostrar la ventana?

Una chorrada: ¿No tendrá el Visible a false?

On Wed, 27 Aug 2008 16:06:22 +0200, Ignacio X. Domínguez
wrote:

Ya estoy llamando el metodo a traves de Invoke y la ventana tiene
TopMost >>> true. El Invoke lo estoy llamando en un delegate. En el hilo principal
no
puedo llamar Invoke porque la clase principal hereda de
ApplicationContext
que no tiene ese metodo. La ventana si se esta creando, pero
simplemente no
se muestra en pantalla aun minimizando todas las ventanas.

Creo que el problema es el thread en el cual se crea la ventana, y ese
es el
problema que no he podido solucionar. Estoy asegurandome que la
ventana se
muestre topmost y fuera de foco mediante llamadas a la API de windows
de la
siguiente manera:

ShowWindow(Handle, SW_SHOWNOACTIVATE);
SetWindowPos(Handle, (IntPtr)HWND_TOPMOST, this.Left, this.Top,
this.Width,
this.Height, SWP_NOACTIVATE);

Funciona perfecto cuando lo llamo desde el hilo de la UI, pero no
cuando
llega la notificación.

Gracias


"RFOG" wrote in message
news:
No he visto tu código en detalle (ya tengo bastante con ver el mío,
je je), pero la forma correcta de tocar código de la UI desde otro
hilo aparte del principal es el de ejecutar ese código desde un
método llamado mediante Invoke.

Luego está el tema de que no te aparece esa ventana. Si lo haces como
arriba seguro que te está apareciendo, lo que ocurre es que al estar
el usuario trabajando con otras, aparece y queda tapada. Para
evitarlo, tienes que poner la propiedad TopMost de la misma a true.

On Tue, 26 Aug 2008 22:36:33 +0200, Ignacio X. Domínguez
wrote:

Un saludo a toda la comunidad.

Estoy desarrollando una aplicacíón de notificación que coloca un
icono en la bandeja y muestra una ventana de notificación cuando
ocurre un evento al estilo messenger y es la clase principal la que
maneja el GUI. Tengo además otra clase con un hilo que cada cierto
tiempo llama a un Web Service. Cuando este servicio devuelve
algunos datos la idea es mostrar la ventana de notificacion. El
problema esta en que cuando se llama el metodo que muestra la
ventana la ventana se crea pero no esta visible. Si hago en cambio
doble click sobre el icono (el evento llama al mismo metodo) la
ventana se muestra perfectamente. El problema creo que esta en que
la ventana creada desde el hilo de notificaciones usa el mismo hilo
y no el hilo del thread. Intente solucionarlo con un delegate y un
evento, luego llamando al metodo Invoke, pero no funciona.

Les muestro el codigo simplificado para ilustrar:

class Notifier : ApplicationContext {
private System.ComponentModel.IContainer components = null;
private NotifyIcon trayIcon;
private ContextMenuStrip trayMenu;

private NotificationChecker nc = null;

[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Notifier());
}

public Notifier() {
this.components = new System.ComponentModel.Container();
this.trayIcon = new NotifyIcon(this.components);
this.trayMenu = new ContextMenuStrip(this.components);
this.trayIcon.ContextMenuStrip = this.trayMenu;
this.trayIcon.DoubleClick += new
EventHandler(trayIcon_DoubleClick);
this.trayIcon.Visible = true;
nc = new NotificationChecker();
nc.NotificationsArrived += new
NotificationsArrivedEventHandler(showNotificationForm);
nc.startChecking();
}

private void trayIcon_DoubleClick(object sender, EventArgs e) {
showNotificationForm();
}

private void showNotificationForm() {
frmNotification fAlert = new frmNotification();
fAlert.Show();
}
}


Ahora el codigo del hilo que llama al web service:



public delegate void NotificationsArrivedEventHandler();

class NotificationChecker {
private Thread thread = null;
private bool started = false;
private NotifierWebService unWebService = null;

public event NotificationsArrivedEventHandler NotificationsArrived;

public NotificationChecker() {
started = false;
unWebService = new NotifierWebService();
unWebService.getNotificationsCompleted += new
getNotificationsCompletedEventHandler(notificationsArrived);
}

private void run() {
while(started) {
unWebService.getNotificationsAsync(settings.UserLogin,
settings.UserPassword);
Thread.Sleep(600000);
}
}

private void notificationsArrived(object sender,
getNotificationsCompletedEventArgs e) {
if(e.Error != null) {
return;
}
else if(e.Result.Length > 0) {
if(NotificationsArrived != null)
NotificationsArrived.Invoke();
}
}

public void startChecking() {
if(!started) {
started = true;
thread = new Thread(new ThreadStart(run));
thread.IsBackground = true;
thread.Start();
}
}

public void stopChecking() {
if(started) {
started = false;
thread.Interrupt();
thread.Abort();
thread = null;
}
}
}


Alguien tiene alguna idea? Gracias de antemano








==>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
>>>> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio,
es un hombre que vende lo que pinta.








==>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
>> Un pintor es un hombre que pinta lo que vende. Un artista, en cambio,
es un hombre que vende lo que pinta.








Microsoft Visual C++ MVP
==Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Cosas mías: http://rfog.blogsome.com/
Libros, ciencia ficción y programación
Un pintor es un hombre que pinta lo que vende. Un artista, en cambio, es
un hombre que vende lo que pinta.
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida