从单独的线程添加菜单项

时间:2009-11-17 21:03:22

标签: .net multithreading compact-framework .net-2.0

我正在一个单独的线程中创建菜单项,并将它们添加到主线程中创建的菜单中。我正在使用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是作为表单初始化例程的一部分创建的。该线程在表单的Activated事件

上启动

2 个答案:

答案 0 :(得分:0)

我认为在没有完全创建控件时会发生这种情况,导致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;
  }

答案 1 :(得分:0)

Hmmmm。每当我调用BeginInvoke时,我总是这样做:

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

IIRC正确我总是使用对象数组,因为在过去没有它我有奇怪的例外。