Ich habe Tray-only-Anwendung sammelt Daten vom Dienst in separaten Thread und aktualisieren Kontextmenü damit.Multithreading und Aktualisierung der Benutzeroberfläche in Nur-Schale-Anwendung,
UI kann nur auf UI-Thread aktualisiert werden, also versuche ich UI update aufzurufen, aber ohne Fenster wird kein Handle erstellt, sodass Invoke InvalidOperationException auslöst und InvokeRequired immer false zurückgibt.
Also, wie kann ich mein Kontextmenü in diesem Fall aktualisieren?
EDIT: Ich eröffne mein Tray-Icon wie folgt aus:
public class TrayIcon : IDisposable
{
NotifyIcon ni;
public TrayIcon()
{
ni = new NotifyIcon();
}
public void Display()
{
ni.Icon = Resources.trayIcon;
ni.Text = "TrayApp";
ni.Visible = true;
ni.ContextMenuStrip = new ContextMenu();
}
public void Dispose()
{
ni.Dispose();
}
}
public static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (TrayIcon icon = new TrayIcon())
{
Settings = new Settings();
icon.Display();
Application.Run();
}
}
EDIT2: Daten innerhalb oBIX Arbeiter Objekt gespeichert ist verfügbar in Anwendung dabei statisch, Event-Handler OnUpdated nach jedem Update auszuführen.
public class ContextMenu: ContextMenuStrip
{
private bool _IsSettingsOpen = false;
private DevicesList DevicesList;
public ContextMenu()
{
DevicesList = new DevicesList();
DevicesList.Text = "Devices";
DevicesList.Image = Resources.online;
Items.Add(DevicesList);
App.Obix.OnUpdated += InvokeUpdate;
}
void InvokeUpdate(object o, EventArgs e)
{
Console.WriteLine(this.IsHandleCreated);//<<false
ContextMenu menu = this;
MethodInvoker method = delegate
{
DevicesList.RePopulate();
};
Invoke(method);//<<InvalidOperationException
}
}
public class DevicesList : ToolStripMenuItem
{
public DevicesList()
{
RePopulate();
}
public void RePopulate()
{
IQueryable<ToolStripItem> listed = (IQueryable<ToolStripItem>)DropDownItems.AsQueryable();
IEnumerable<ToolStripItem> remove = listed.Where(item => !App.Obix.Devices.Contains(new DeviceStatus(item.Name)));
foreach (ToolStripItem rItem in remove)
{
DropDownItems.Remove(rItem);
}
IEnumerable<DeviceStatus> add = App.Obix.Devices.Where(device => DropDownItems.IndexOfKey(device.Name) == -1);
foreach (DeviceStatus aDevice in add)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Name = aDevice.Name;
item.Text = aDevice.Name;
DropDownItems.Add(item);
}
foreach (ToolStripMenuItem item in DropDownItems)
{
DeviceStatus device = App.Obix.Devices.Single(_device => _device.Name == item.Name);
if (device.State == "down")
item.Image = Resources.offline;
else
item.Image = Resources.online;
}
}
}
}
Zeigen Sie den Code an, der die Benutzeroberfläche aktualisiert. – CodeCaster
Ihr Code verfügt nicht über das von Ihnen erwähnte "Invoke" oder "InvokeRequired". – mjwills
@CodeCaster Bearbeitete meine Frage –