2009-11-17 3 views
0

Je crée des éléments de menu dans un fil distinct et les ajoute au menu créé dans le fil principal. J'utilise Invoke pour ça. Obtenir l'exception "La valeur ne correspond pas à la fourchette attendue".Ajout d'éléments de menu à partir d'un fil distinct

  //creating new thread 
      Thread thread = new Thread(LoadRecentTasks); 
      thread.IsBackground = true; 
      thread.Start(); 

    private void LoadRecentTasks() 
    { 
     EntryCollection recentEntries = Entry.GetRecentEntries(10); 
     foreach (Entry entry in recentEntries) 
     { 
      MenuItemPlus menuItem = new MenuItemPlus(); 
      menuItem.Text = entry.GetShortDescription(28); 
      menuItem.Click += recentTasksMenuItem_Click; 
      menuItem.Tag = entry; 
      AddRecentMenuItem(menuItem); 
     } 
    } 

    private void AddRecentMenuItem(MenuItemPlus menuItem) 
    { 
     if (InvokeRequired) 
     { 
      BeginInvoke(new CallbackDelegate<MenuItemPlus>(AddRecentMenuItem), menuItem); 
     } 
     else 
     { 
      menuItemRecent.MenuItems.Add(menuItem); //<-- exception thrown here 
     } 
    } 

    delegate void CallbackDelegate<T>(T t); 

Des suggestions? MISE À JOUR: je l'ai essayé avec Invoke aussi - même résultat. MenuItemRecent est créé dans le cadre de la routine d'initialisation du formulaire. Le thread est démarré sur l'événement Activé du formulaire

+0

Quelle ligne de code lève l'exception? –

+0

J'ai supposé celui qu'il a commenté :) Pour une raison quelconque, je pensais que BeginInvoke avait besoin d'un tableau d'arguments au lieu d'un seul objet, mais si c'était le cas, je doute que le code compile même. – SimonJ

+0

@SimonJ. ha ha, suis-je aveugle ou suis-je aveugle? Cela semble tout à fait raisonnable ... –

Répondre

0

Je suppose que cela se produit lorsque le contrôle n'est pas entièrement créé, entraînant InvokeRequired à vous donner une fausse lecture.

 /// <summary> 
    /// It's possible for InvokeRequired to return false when running in background thread. 
    /// This happens when unmanaged control handle has not yet been created (need to throw). 
    /// This can also happen when control is created on background thread (need to debug.assert). 
    /// </summary> 
    /// <param name="control">Control to check against.</param> 
    public bool InvokeRequired(Control control) 
    { 
    return InvokeRequired(control, false); 
    } 

    /// <param name="backgroundControl">If set to true, will not assert when control on background thread. </param> 
    public bool InvokeRequired(Control control, bool controlOnBackgroundByDesign) 
    { 
    if (control.InvokeRequired) 
     return true; 

    if (!control.IsHandleCreated) 
     Debug.WriteLine("Control access issue: Underlying control handle has not been created yet. At this point in time cannot reliably test if invoke is required."); 

    if (!controlOnBackgroundByDesign) 
    { 
     // Check for control on background thread. 
     if(!this.IsOnUiThread) 
      Debug.WriteLine("Control access issue: It's recommended that all controls reside on a single foreground thread."); 
    } 

    // At this point, program is executing on control's thread. 
    return false; 
    } 
+0

Bien sûr, cet exemple de code est incomplet, donc je ne peux pas repro et debug pour vous. – GregC

+0

Merci, Greg. menuItemRecent est créé dans le cadre de la routine d'initialisation du formulaire. Le thread est démarré sur l'événement Activé du formulaire. – Muxa

+0

Avez-vous eu l'occasion d'essayer le remplacement InvokeRequired fourni? Cela a-t-il fonctionné comme prévu ou avez-vous reçu des messages dans le panneau de sortie de débogage? – GregC

0

Hmmmm. Chaque fois que j'appelle BeginInvoke je fais toujours ceci:

BeginInvoke(new CallbackDelegate<MenuItemPlus>(AddRecentMenuItem), new object[]{menuItem}); 

IIRC correctement J'utilise toujours le tableau d'objets, car sans elle dans le passé, j'ai des exceptions étranges.

Questions connexes