我正在一个单独的线程中创建菜单项,并将它们添加到主线程中创建的菜单中。我正在使用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事件
上启动答案 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正确我总是使用对象数组,因为在过去没有它我有奇怪的例外。