我目前正在尝试了解.net中的计时器如何处理多线程应用程序。使用Visual Studio 2010,.NET / C ++ / CLI 任务是有一个计时器,将在后台读取一些数据,以便我可以通过另一个计时器显示该数据。虽然很简单......
我做了一个简单的程序来观察不同的计时器是如何工作的:
1. System :: Windows :: Forms :: Timer ;
2. 系统::计时器::计时器;
3. 系统::线程::计时器;
4.和另一个 System :: Timers :: Timer ,我不是从主线程运行,而是使用System :: Threading :: Thread 。
所有这些都是在代码中手动制作的,还有另一个在Designer中制作的计时器,类型为System :: Windows :: Forms :: Timer
每个计时器在每个tick中为其自己的 ConcurrentQueue 类型的容器写一个字符串,并递增其计数器,即int类型的全局变量。主线程计时器将这些字符串获取到接口列表Control。
programm snapshot
所有四个定时器初始化为每500ms滴答一次
列表中的第一个数字是刻度计数器。 <> 中的文字是主题名称。
Id:是该主题的ID。
T:是在每个事件中使用 QueryPerformanceCounter()函数计算的滴答之间的实时时间。
现在我们看到计时器开始同时工作前5个刻度。我们也看到只有第一个计时器每个滴答使用相同的线程
然后我按下睡眠按钮,在主线程上实现睡眠(5000)功能,模仿它真的很忙。
正如预期的那样,第一个只是在睡眠后停止并继续
但是其他人对我来说很奇怪。我希望它们能在后台运行。但我所看到的是,计数器没有正确递增,并且刻度的时间也不正确。
我想知道的是那些定时器(Timers :: Timer和Threading :: Timer)真的以某种方式被主线程休眠函数阻止,或者它只是一个 UI bug /代码错误 或他们 工作正常 ?
这里定时器滴答会发生什么。与每个计时器类似:
System::Void Form1::SysThrd_Tick(System::Object^ sender)
{
static LARGE_INTEGER ticks_old, ticks_new; //for precise counter
double real_time=0;
if (Thread::CurrentThread->Name == nullptr) Thread::CurrentThread->Name = "ThTm";
Thread_Timer_Id = GetThreadId(GetCurrentThread());
QueryPerformanceCounter(&ticks_new); //getting precise ticks
real_time = safe_cast<double>(ticks_new.QuadPart - ticks_old.QuadPart);
real_time = real_time/freq.QuadPart; //counting real time passed for tick
ThTm_queue->Enqueue(SysThrd_tick.ToString()+" <"+Thread::CurrentThread->Name+"> Id: "+Thread_Timer_Id+"; T: "+real_time.ToString("0.000")); //adding item to container
SysThrd_tick++;
ticks_old = ticks_new;
}
通过设计器计时器显示容器中的数据:
System::Void Form1::InnerTimer_Tick(System::Object^ sender, System::EventArgs^ e)
{
String ^str;
static int Inner_tick=0;
InnerTimer_tB->Text = Thread::CurrentThread->Name+"::"+Inner_tick.ToString(); //text to Form1 TextBox control
Inner_tick++;
while (!ThTm_queue->IsEmpty)
{
ThTm_queue->TryDequeue(str); //getting item from container
Threading_Timer_lB->Items->Add(str); //adding item to Form1 ListBox control
}
//<similar code for other containers>
}
在Form1.h中定义的所有容器,并在main.cpp中初始化,如下所示:
void Form1::init_queues()
{
ThTm_queue = gcnew ConcurrentQueue<String^>;
//same code for other containers
}
Tick计数器是全局整数,在resource.h中定义
定时器在Form1.h中定义并在main.cpp中初始化,例如Threading :: Timer:
System::Void Form1::Init_Timers()
{
//other timers initialization
Form1::SysThrd_Timer = gcnew System::Threading::Timer((gcnew TimerCallback(this, &Form1::SysThrd_Tick)), nullptr, Threading::Timeout::Infinite, Threading::Timeout::Infinite);
}