我正在玩托盘应用程序。应用程序仅在系统托盘中运行,并且没有与之关联的Windows窗体。应用程序使用ManagementEventWatcher并在某些情况下显示警报窗口。
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AppContext());
}
...
public class AppContext : ApplicationContext
{
private System.ComponentModel.IContainer _components;
private NotifyIcon _notifyIcon;
private ContextMenuStrip _contextMenu;
private ManagementEventWatcher _regWatcher;
public AppContext()
{
//Initialize context menu & tray icon
_regWatcher = new ManagementEventWatcher(query);
_regWatcher.EventArrived += new EventArrivedEventHandler(_regWatcher_EventArrived);
_regWatcher.Start();
}
void _regWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Alert.Show("Alert!", "My Message", someParam);
}
}
...
public class Alert
{
public static void Show(string title, string message, string extraInfo)
{
new Alert(title, message, extraInfo).ShowDialog();
}
private Alert(string title, string message, string extraInfo)
{
InitializeComponent();
this.Icon = Properties.Resources._default;
this.Text = title;
this.label1.Text = message;
this.linkLabel1.Text = extraInfo;
}
}
有趣的是,它并没有抱怨没有以线程安全的方式访问UI。我想因为它只存在于这个后台线程中。但是稍后当Form尝试访问剪贴板时,它不起作用,因为它在MTA线程上运行。到目前为止,我发现的所有类似问题都已经有一个调用Invoke的表单,或者可以选择使用BackgroundWorker。在这种情况下,在主线程上创建和显示警报表单的最佳方法是什么?
答案 0 :(得分:0)
感谢Idle_Mind与Andy Whitfield's blog post的链接,我已经找到了解决方案。我向AppContext类添加了一个私有全局SynchronizationContext。在构造函数中,我将其初始化为WindowsFormsSynchronizationContext的实例。然后,当注册表观察者的事件发生时,我可以将任务发回主线程。
public class AppContext : ApplicationContext
{
private SynchronizationContext _uiThreadContext;
...
public AppContext()
{
//Initialize context menu & tray icon
_uiThreadContext = new WindowsFormsSynchronizationContext();
_regWatcher = new ManagementEventWatcher(query);
_regWatcher.EventArrived += new EventArrivedEventHandler(_regWatcher_EventArrived);
_regWatcher.Start();
...
}
private void _regWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
...
_uiThreadContext.Post(new SendOrPostCallback(MyEventHandler), parameters)
}