Добавление пунктов меню из отдельного потока - PullRequest
0 голосов
/ 18 ноября 2009

Я создаю пункты меню в отдельном потоке и добавляю их в меню, созданное в основном потоке. Я использую Invoke для этого. Получение исключения «Значение не попадает в ожидаемый диапазон».

            //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);

Есть предложения?

ОБНОВЛЕНИЕ: я тоже пробовал с Invoke - тот же результат.

menuItemRecent создается как часть процедуры инициализации формы. Поток запускается при активированном событии формы

Ответы [ 2 ]

0 голосов
/ 19 ноября 2009

Хммм. Всякий раз, когда я вызываю BeginInvoke, я всегда делаю это вместо:

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

IIRC правильно. Я всегда использую массив объектов, потому что без него в прошлом у меня возникали странные исключения.

0 голосов
/ 18 ноября 2009

Я предполагаю, что это происходит, когда элемент управления создан не полностью, в результате чего InvokeRequired выдает ложное чтение.

      /// <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;
  }
...