c# - ContexMenuStrip oddly-specific weird behaviour -


i testing weird bug encountered in app, , able create simple reproduction:

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 different thread 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();     } } 

note context menu not open, doing of following allows open:

  • removing "extra" dropdown items added per execution. (to precise adding 0 or 1 per execution works)
  • removing part of code on invokerequired == false (this allows add multiple items per execution)
  • removing t1 , t2 elements. (it still works without additional items in root)

is bug or doing wrong?

edit: additional found condition (thanks @derape):

  • it works if move else branch separate method, not if use same method in invokerequired branch. using 2 method different name , same code works.

possible workaround wearing tigers skin while dancing during full-moon.

if @ invokerequired see there explicit check ishandlecreated returns false. returned value doesn't means don't have invoke, means can not invoke.

to confuse more: must invoke, can't yet.

you can either decide don't if handle not created yet (and miss items) or organize separate queue store items until handle available, similar to:

var items = new list<string>(); timer.elapsed += (sender, e) => {     if (contextmenustrip1.ishandlecreated)  // invoke, check 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; }; 

another note: need call refresh if items added sub-menu, while menu opened, submenu not yet, odd thing of winforms.


Comments

Popular posts from this blog

python - Operations inside variables -

Generic Map Parameter java -

arrays - What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? -