.net 从单独的线程添加菜单项
我在一个单独的线程中创建菜单项,并将它们添加到主线程中创建的菜单中。我正在使用Invoke。获取“值不在预期范围内”异常.net 从单独的线程添加菜单项,.net,multithreading,compact-framework,.net-2.0,.net,Multithreading,Compact Framework,.net 2.0,我在一个单独的线程中创建菜单项,并将它们添加到主线程中创建的菜单中。我正在使用Invoke。获取“值不在预期范围内”异常 //creating new thread Thread thread = new Thread(LoadRecentTasks); thread.IsBackground = true; thread.Start(); private void LoadRecentTa
//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);
//创建新线程
线程线程=新线程(LoadRecentTasks);
thread.IsBackground=true;
thread.Start();
私有void LoadRecentTasks()
{
EntryCollection recentEntries=Entry.getRecentries(10);
foreach(最近的条目)
{
menuitempus menuItem=新的menuitempus();
menuItem.Text=entry.GetShortDescription(28);
menuItem.Click+=recentTasksMenuItem\u单击;
menuItem.Tag=条目;
AddRecentMenuItem(menuItem);
}
}
私有void AddRecentMenuItem(MenuTempus menuItem)
{
如果(需要调用)
{
BeginInvoke(新CallbackDelegate(AddRecentMenuItem)、menuItem);
}
其他的
{
menuItemRecent.MenuItems.Add(menuItem);//我假设在未完全创建控件时会发生这种情况,从而导致invokererequired提供错误的读数
/// <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;
}
//
///在后台线程中运行时,invokererequired可能返回false。
///如果尚未创建非托管控件句柄(需要抛出),则会发生这种情况。
///在后台线程上创建控件时也会发生这种情况(需要debug.assert)。
///
///控件进行检查。
需要公共布尔调用(控制)
{
返回invokererequired(控件,false);
}
///如果设置为true,则在后台线程上执行控件时不会断言。
需要公共bool调用(控制控制,bool控制背景设计)
{
if(control.invokererequired)
返回true;
如果(!control.IsHandleCreated)
WriteLine(“控件访问问题:尚未创建底层控件句柄。此时无法可靠地测试是否需要调用。”);
if(!controlOnBackgroundByDesign)
{
//检查后台线程上的控件。
如果(!this.IsOnUiThread)
WriteLine(“控件访问问题:建议所有控件都驻留在一个前台线程上。”);
}
//此时,程序正在控件的线程上执行。
返回false;
}
Hmmmm。每当我打电话给BeginInvoke时,我总是这样做:
BeginInvoke(new CallbackDelegate<MenuItemPlus>(AddRecentMenuItem), new object[]{menuItem});
BeginInvoke(新回调委托(AddRecentMenuItem),新对象[]{menuItem});
IIRC正确地说,我总是使用对象数组,因为在过去没有对象数组,我会遇到奇怪的异常。哪一行代码会引发异常?我假设是他评论的那一行:)出于某种原因,我认为BeginInvoke需要一个参数数组而不是一个对象,但如果是这样的话,我怀疑代码是否能够编译。@SimonJ.哈哈,我是瞎子还是瞎子?听起来很合理…当然,这个代码示例不完整,所以我不可能为你重新编译和调试。谢谢,Greg。menuItemRecent是作为表单初始化例程的一部分创建的。线程是在表单的激活事件上启动的。你有机会尝试提供的InvokeRequired替换吗Monte?它是否按计划工作,或者您是否在调试输出面板中收到一些消息?我认为InvokeRequired不可能在CF中给出错误的值。CF中控件上的InvokeRequired非常简单。它只需要在Ctor中创建它的线程id,然后将它与InvokeRequired中的当前线程id进行比较。我已经用y尝试过了我们的代码。两个问题:IsHandleCreated和IsUnuithRead在不可用的地方(我使用了.NET CF 2.0)我尝试了(control.Handle==IntPtr.Zero)而不是(!control.IsHandleCreated)-从未出现过这种情况。我在想,可能可以在主UI线程中创建菜单项,但可以将对象引用返回到第二个线程。伪代码:LoadRecentTasks(){foreach(recentEntries中的条目){AddRecentMenuItem(MainUIThread.NewMenuItem());}}