2010-10-18 8 views
7

En mi aplicación, estoy usando un temporizador para buscar actualizaciones en un canal RSS, si se encuentran nuevos elementos, aparece un cuadro de diálogo personalizado para informar al usuario. Cuando ejecuto el control de forma manual, todo funciona bien, pero cuando la comprobación automática se ejecuta en el evento de Tiempo transcurrido, el cuadro de diálogo personalizado no se muestra.Método de llamada en el subproceso GUI desde un subproceso de temporizadores

Primero de todo, ¿esto es un problema de rosca? (Estoy asumiendo que es porque tanto el cheque manual como el automático usan el mismo código).

Cuando ejecuto la comprobación automática, ¿tengo que invocar el método que ejecuta la verificación desde el controlador de eventos de Tiempo transcurrido?

¿Hay algo que deba hacer en mi clase de diálogo personalizada?

Editar: esta es una aplicación de winforms.

Aquí hay un ejemplo de cómo es el código. (Por favor, no señale los errores de sintaxis en este ejemplo de código, esto es solo un ejemplo simple, no es un código real).

public class MainForm : System.Windows.Forms.Form 
{ 
    //This is the object that does most of the work. 
    ObjectThatDoesWork MyObjectThatDoesWork = new ObjectThatDoesWork(); 
    MyObjectThatDoesWork.NewItemsFound += new NewItemsFoundEventHandler(Found_New_Items); 

    private void Found_New_Items(object sender, System.EventArgs e) 
    { 
     //Display custom dialog to alert user. 
    } 

    //Method that doesn't really exist in my class, 
    // but shows that the main form can call Update for a manual check. 
    private void Button_Click(object sender, System.EventArgs e) 
    { 
     MyObjectThatDoesWork.Update(); 
    } 

    //The rest of MainForm with boring main form stuff 
} 


public class ObjectThatDoesWork 
{ 
    System.Timers.Timer timer; 

    public ObjectThatDoesWork() 
    { 
     timer = new System.Timers.Timer(); 
     timer.Interval = 600000; 
     timer.AutoReset = true; 
     timer.Elapsed += new new System.Timers.ElapsedEventHandler(TimeToWork); 
     timer.Start(); 
    } 

    private void TimeToWork(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     Update(); 
    } 

    public void Update() 
    { 
     //Check for updates and raise an event if new items are found. 
     //The event is consumed by the main form. 
     OnNewItemsFound(this); 
    } 

    public delgate void NewItemsFoundEventHandler(object sender, System.EventArgs e); 
    public event NewItemsFoundEventHandler NewItemsFound; 
    protected void OnNewItemsFound(object sender) 
    { 
     if(NewItemsFound != null) 
     { 
      NewItemsFound(sender, new System.EventArgs()); 
     } 
    } 
} 

Después de leer algunos de los comentarios y respuestas, creo que mi problema es que no estoy usando un System.Timers.Timer un System.Windows.Forms.Timer.

EDIT:

Después de cambiar a una prueba inicial Forms.Timer se ve bien (pero que aún no existen nuevos elementos para que no han visto el diálogo personalizado). Agregué un poco de código para enviar la ID del hilo a un archivo cuando se llama al método de actualización. Uso de los temporizadores. El temporizador de la identificación del subproceso no era el subproceso de GUI, sino que utilizaba los formularios. El temporizador de la identificación del subproceso es el mismo que el de la GUI.

+3

Sí, es un problema de enhebrado, pero la respuesta depende de si está utilizando WPF o WinForms: ¿cuál es? – x0n

+0

Y me sorprende que no vea ninguna excepción: ¿en qué versión de .NET está ejecutando esto? ¿Puedes mostrar un código de muestra? –

+0

¿Puedes publicar el código? – TalentTuner

Respuesta

15

Which timer ¿estás usando? System.Windows.Forms.Timer activa automáticamente el evento en el hilo de UI. Si está usando otro, necesitará usar Control.Invoke para llamar al método en el hilo de UI.

+0

Cambiando a System.Windows.Forms.Timer resolvió el problema. Gracias. – Tester101

+0

+1000! System.Windows.Forms.Timer resuelve todos mis frustrantes problemas de temporizador "Objeto creado en otro hilo". ¡Gracias! –

+0

como una broma, ¡pasé un día para eso! Gracias y ten en cuenta – aozan88

1

Debe utilizar Forms.Timer aquí, o si se utiliza otro tipo de temporizadores, serializar las llamadas a la interfaz de usuario con .Invoke()

0
private static System.Threading.SynchronizationContext _UI_Context; 
    //call this function once from the UI thread 
    internal static void init_CallOnUIThread() 
    { 
     _UI_Context = System.Threading.SynchronizationContext.Current; 
    } 
    public static void CallOnUIThread(Action action, bool asynchronous = false) 
    { 
     if (!asynchronous) 
      _UI_Context.Send((o) => 
      { 
       action(); 
      }, null); 
     else 
      _UI_Context.Post((o) => 
      { 
       action(); 
      }, null); 
    } 
Cuestiones relacionadas