我正在测试我在应用中遇到的一个奇怪的错误,最后能够创建一个简单的复制:
using System;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var notifyIcon1 = new NotifyIcon();
notifyIcon1.Icon = new Form().Icon;
notifyIcon1.Visible = true;
var contextMenuStrip1 = new ContextMenuStrip();
ToolStripMenuItem menu1 = new ToolStripMenuItem();
menu1.Text = "test";
contextMenuStrip1.Items.Add(menu1);
contextMenuStrip1.Items.Add("t1");
contextMenuStrip1.Items.Add("t2");
notifyIcon1.ContextMenuStrip = contextMenuStrip1;
var timer = new System.Timers.Timer();
timer.Interval = 3000;
timer.Elapsed += (sender, e) => /* Runs in a different thread from UI thread.*/
{
if (contextMenuStrip1.InvokeRequired)
contextMenuStrip1.Invoke(new Action(() =>
{
menu1.DropDownItems.Add(e.SignalTime.ToString() + "extra");
menu1.DropDownItems.Add(e.SignalTime.ToString());
}));
else
{
menu1.DropDownItems.Add(e.SignalTime.ToString() + "extra");
menu1.DropDownItems.Add(e.SignalTime.ToString());
}
};
timer.Start();
Application.Run();
}
}
请注意,上下文菜单不会打开,但执行以下任何操作都可以打开:
InvokeRequired == false
上的部分代码(这允许每次执行添加多个项目)t1
和t2
元素。 (它仍然没有
根目录中的其他项目这是一个错误还是我做错了什么?
编辑: 额外的条件(感谢@derape):
可能的解决方法是在满月时跳舞时穿着老虎的皮肤。
答案 0 :(得分:1)
如果您查看InvokeRequired
,您会看到IsHandleCreated
的明确检查会返回false
。返回值并不意味着您不必调用,它只是意味着您无法调用。
让你更加困惑:你必须调用,但你还不能。
如果还没有创建句柄(并且只是遗漏项目),或者组织单独的队列来存储项目直到句柄可用,您可以决定不做任何事情,类似于:
var items = new List<string>();
timer.Elapsed += (sender, e) =>
{
if (contextMenuStrip1.IsHandleCreated) // always invoke, but check for handle
contextMenuStrip1.Invoke(new Action(() =>
{
menu1.DropDownItems.Add(e.SignalTime.ToString() + "extra");
menu1.DropDownItems.Add(e.SignalTime.ToString());
contextMenuStrip1.Refresh();
}));
else
{
lock (items)
{
items.Add(e.SignalTime.ToString() + "extra");
items.Add(e.SignalTime.ToString());
}
}
};
contextMenuStrip1.HandleCreated += (s, e) =>
{
lock (items)
{
foreach (var item in items)
menu1.DropDownItems.Add(item);
contextMenuStrip1.Refresh();
}
items = null;
};
另一个注意事项:如果项目已添加到子菜单,则需要调用Refresh
,同时菜单已打开,但子菜单尚未显示,这是winforms的奇怪之处。