在控制台应用程序中调用statthread的c#定时器
本文关键字:定时器 statthread 调用 控制台 应用程序 | 更新日期: 2023-09-27 18:06:18
我有一个控制台应用程序,它需要触发一个使用COM的方法。程序从[STAThread]开始。当不使用计时器进程时,程序可以正确执行,但当使用计时器进程时,显然会阻塞回控制台。
我用过System.Threading.Timer和System.Timers.Timer,但都不起作用。目前,我添加了一个使用COM调用方法(Transmit())的线程。如果我用控制台清除主线程。Readline程序在COM对象被阻塞的地方恢复,但当然程序随后关闭,我失去了期望的计时器功能。
我不知道如何设置SynchronizingObject来获得一个ISynchronizeInvoke回调,当使用控制台应用程序。
我不是在寻找多个线程,我只需要定期调用传输方法,并与COM一起工作,同时将结果返回到控制台。
class Program
{
private static System.Timers.Timer transTimer;
[STAThread]
static void Main(string[] args)
{
transTimer = new System.Timers.Timer();
transTimer.Enabled = true;
transTimer.Interval = 6000;
transTimer.Elapsed += new System.Timers.ElapsedEventHandler(transTimer_Elapsed);
transTimer.Start();
Console.ReadLine();
transTimer.Dispose();
return;
}
static void transTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (transTimer.Enabled)
{
transTimer.Enabled = false;
Thread thread = new Thread(Transmit);
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
thread.Start();
thread.Join(); //Wait for the thread to end
transTimer.Enabled = true;
}
}
您违反了重要的单线程公寓(STA)要求,它必须泵送消息循环。没有它,COM就不能封送从工作线程到创建COM组件的线程的调用。这对于确保以线程安全的方式使用组件是必要的。问题不在于你使用了计时器,而在于你使用了线程。可观察到的结果是调用死锁。
在控制台应用程序中获取消息循环是很难实现的。一种解决方法是不要在Main()方法中创建COM组件,而是让工作线程创建它,这样就不需要封送处理。通过在循环中调用Sleep()来实现周期调用。 另一个解决方法是不使用[STAThread]属性。然后,COM将自动创建一个STA线程,为COM组件提供一个安全的家。这个线程还输出一个消息循环。现在每个调用都将被封送,如果您进行了很多调用,请避免。. net中设置消息泵的方法是Application.Run()。从一个单独的专用线程调用它,并使用不接受表单的重载。把你的COM代码放在那个线程上,把你的控制台代码放在主线程上,这样控制台阻塞你的COM逻辑就不会有任何问题。如果你需要一个计时器来与COM逻辑交互,使用System.Windows.Forms.Timer对象,创建一个在COM线程上启动的对象。这样,它的回调/事件也将在COM线程上运行。