从定时器线程调用GUI线程上的方法

在我的应用程序中,我使用计时器来检查RSS提要中的更新,如果找到新项目,我会弹出一个自定义对话框来通知用户。 当我手动运行检查时,一切都很好,但是当自动检查在计时器Elapsed事件中运行时,不会显示自定义对话框。

首先是这是一个线程问题? (我假设这是因为手动和自动检查都使用相同的代码)。

当我运行自动检查时,是否必须从Timers Elapsed事件处理程序调用运行检查的方法?

我的自定义对话框类中是否需要执行某些操作?

编辑:这是一个winforms应用程序。

以下是代码的示例。 (请不要在此代码示例中指出语法错误,这只是一个简单的示例,而不是真正的代码)。

public class MainForm : System.Windows.Forms.Form { //This is the object that does most of the work. ObjectThatDoesWork MyObjectThatDoesWork = new ObjectThatDoesWork(); MyObjectThatDoesWork.NewItemsFound += new NewItemsFoundEventHandler(Found_New_Items); private void Found_New_Items(object sender, System.EventArgs e) { //Display custom dialog to alert user. } //Method that doesn't really exist in my class, // but shows that the main form can call Update for a manual check. private void Button_Click(object sender, System.EventArgs e) { MyObjectThatDoesWork.Update(); } //The rest of MainForm with boring main form stuff } public class ObjectThatDoesWork { System.Timers.Timer timer; public ObjectThatDoesWork() { timer = new System.Timers.Timer(); timer.Interval = 600000; timer.AutoReset = true; timer.Elapsed += new new System.Timers.ElapsedEventHandler(TimeToWork); timer.Start(); } private void TimeToWork(object sender, System.Timers.ElapsedEventArgs e) { Update(); } public void Update() { //Check for updates and raise an event if new items are found. //The event is consumed by the main form. OnNewItemsFound(this); } public delgate void NewItemsFoundEventHandler(object sender, System.EventArgs e); public event NewItemsFoundEventHandler NewItemsFound; protected void OnNewItemsFound(object sender) { if(NewItemsFound != null) { NewItemsFound(sender, new System.EventArgs()); } } } 

在阅读了一些评论和答案后,我认为我的问题是我使用的是System.Timers.Timer而不是System.Windows.Forms.Timer

编辑:

更改为Forms.Timer之后,初始测试看起来很好(但是没有新项目存在,所以没有看到自定义对话框)。 我在调用update方法时添加了一些代码来将线程ID输出到文件中。 使用Timers.Timer,线程ID不是GUI线程,但使用Forms.Timer,线程ID与GUI相同。

你在用哪个计时器 ? System.Windows.Forms.Timer自动在UI线程上触发事件。 如果您正在使用其他的,则需要使用Control.Invoke在UI线程上调用该方法。

你应该在这里使用Forms.Timer,或者如果你使用其他类型的计时器,使用.Invoke()序列化对UI的调用

您的应用程序是WPF应用程序吗? 如果是这样,您必须将工作从后台线程委派给与UI线程关联的Dispatcher。

发布一些代码,以便您可以获得更好的帮助,并查看Dispatcher类http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx

  private static System.Threading.SynchronizationContext _UI_Context; //call this function once from the UI thread internal static void init_CallOnUIThread() { _UI_Context = System.Threading.SynchronizationContext.Current; } public static void CallOnUIThread(Action action, bool asynchronous = false) { if (!asynchronous) _UI_Context.Send((o) => { action(); }, null); else _UI_Context.Post((o) => { action(); }, null); }