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

#11 Paulino Padial López
02/10/2008 - 15:56 | Informe spam
Yo hace poco hize una aplicación que digamos, periodicamente consulta
una base de datos en background para ver si hay tareas nuevas.
En caso de haber alguna, me muestra un formulario tipo messenger con los
datos de la tarea, y al hacer click en el formulario me abre otro con
los datos de la tarea.

Yo lo hize con un Background Worker, ya que el se encarga de gestionar
su "hebra" y ademas me permite pasarle como parametros los forms,
objetos o lo que quiera usar desde su "hebra".

Tengo el proyecto en casa, si quieres te lo peudo mandar, o lo coloco en
un lugar publico para que le heches un vistazo :)

saludos cordiales,



Ignacio X. Domínguez escribió:
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



email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida