在我的应用程序中,我使用计时器检查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相同。
答案 0 :(得分:18)
Which timer吗? System.Windows.Forms.Timer自动在UI线程上触发事件。如果您使用的是其他人,则需要使用Control.Invoke在UI线程上调用该方法。
答案 1 :(得分:1)
您应该在此处使用Forms.Timer,或者如果您使用其他类型的计时器,请使用.Invoke()
序列化对UI的调用
答案 2 :(得分:0)
您的应用程序是WPF应用程序吗?如果是这样,您必须将工作从后台线程委派给与UI线程关联的Dispatcher。
发布一些代码,以便您可以获得更好的帮助,并查看Dispatcher类http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx
答案 3 :(得分:0)
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);
}