你好,我正在尝试让Timer.Timer类的Elapsed事件在我的主线程上触发。 我只能使用VS 2008,.net 3.5…… 在这篇帖子中: Do C# Timers elapse on a separate thread? 其中提到使用SynchronizingObject将使处理程序在拥有该对象的线程上执行。
所以我尝试了这个:
class MyTimer
{
private readonly Timer timer;
public MyTimer(ISynchronizeInvoke synchronizingObject)
{
Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
timer = new Timer(1000);
timer.SynchronizingObject = synchronizingObject;
timer.Elapsed +=
delegate
{
timer.Stop();
Thread.Sleep(2000);
Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
timer.Start();
};
timer.Start();
}
}
class Program
{
static void Main(string[] args)
{
ISynchronizeInvoke syncObject = new Control();
var mytimer = new MyTimer(syncObject);
Console.ReadKey();
}
}
但是输出结果为:1,4,4,4,4...
为什么会这样呢?我该如何使Elapsed手柄在主线程上执行。
我尝试使用事件的同步对象,但也没能解决问题。
public static ElapsedEventHandler Wrap(ElapsedEventHandler original, ISynchronizeInvoke synchronizingObject)
{
return (sender, args) =>
{
if (synchronizingObject.InvokeRequired)
{
synchronizingObject.Invoke(original, new object[] { sender, args });
}
else
{
original(sender, args);
}
};
}
并且:
timer.Elapsed += Wrap(
delegate
{
timer.Stop();
Thread.Sleep(200);
Console.Out.WriteLine(Thread.CurrentThread.ManagedThreadId);
timer.Start();
},
synchronizingObject);
但是仍然没有成功......每次调用InvokeRequired都返回false......
强制进行调试时,会引发无效操作:"在控件的窗口句柄创建之前,无法调用Invoke或BeginInvoke。"
最后的办法是看看:http://www.codeproject.com/Articles/12082/A-DelegateQueue-Class?msg=3655119#xx3655119xx,但这真的有必要吗?还是有更简单的解决方案吗?
Application.Run()
来启动消息泵。然后,您需要调用Application.Exit()
来“关闭”主线程。然而,在我看来,OP 的 Dispatcher 解决方案更好,因为它不会让您依赖 Winforms。 - Scott Chamberlain