首先介绍下背景,我的线程是我自己创建的,里面需要用到复杂的算法,但完全不需要系统调用(当然也不需要分配内存)。你可以把他假想为一个对大量数据排序的算法。另外我的线程有一定的实时性要求,可以认为系统有一个电眼提供外部触发信号,在下一个触发信号到达前,必须处理完当前信号。目前考虑有3种办法:
1、在复杂算法内部经常性去判断下一个触发信号是否已到达,流程大致如下:
算法步骤1;
下一信号是否到达?到达则返回;
算法步骤2;
下一信号是否到达?到达则返回;
算法步骤3;
下一信号是否到达?到达则返回;
......
缺点:算法本身相当复杂,并不好简单的分为几个步骤,且相邻两次检查信号之间的步骤会运行多久,也很难估计(每次信号不同,使得算法每个步骤需要的时间也可能不同),这样就有可能下一信号已经到达一段时间后,才会停止处理当前信号。当前信号晚点处理完倒没什么关系,反正结果都没用了。但问题是可能造成下一种办法提到的连锁反应。
另外这种做法本身对算法程序的独立性/维护性都会造成影响。2、不终止当前信号的线程,让它自然结束。新建线程处理新的信号。
缺点:系统负荷不大时,这也是个办法。但系统负荷较大时,很可能当前信号的线程占用CPU,导致下一信号也不能被及时处理,从而造成连锁反应。甚至可能系统中线程越来越多,最终崩溃。3、在下一个触发信号到达时,如果当前信号未处理结束则使用TerminateThread强行终止。
这个方法应该能够克服上面的两个缺点,但查了好几天,都说TerminateThread会造成泄漏。《Windows 核心编程》提到,线程函数返回时能够确保:
1.在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
2.操作系统将正确地释放线程堆栈使用的内存。
3.系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
4.系统将递减线程内核对象的使用计数。由于我的线程不会分配内存,所以主要问题应该在“释放线程堆栈”和“递减线程内核对象的使用计数”。我的问题是:
1.确实没有办法TerminateThread后释放线程堆栈吗?
2.TerminateThread后,通过CloseHandle是否可以达到“递减线程内核对象的使用计数”的效果?我觉得我的这个需求在一些需要实时进行产品检测的流水线上是很常见的,应该有比较好的解决办法才对。期望高手给予解答,非常感谢!分不够了,惭愧
1、在复杂算法内部经常性去判断下一个触发信号是否已到达,流程大致如下:
算法步骤1;
下一信号是否到达?到达则返回;
算法步骤2;
下一信号是否到达?到达则返回;
算法步骤3;
下一信号是否到达?到达则返回;
......
缺点:算法本身相当复杂,并不好简单的分为几个步骤,且相邻两次检查信号之间的步骤会运行多久,也很难估计(每次信号不同,使得算法每个步骤需要的时间也可能不同),这样就有可能下一信号已经到达一段时间后,才会停止处理当前信号。当前信号晚点处理完倒没什么关系,反正结果都没用了。但问题是可能造成下一种办法提到的连锁反应。
另外这种做法本身对算法程序的独立性/维护性都会造成影响。2、不终止当前信号的线程,让它自然结束。新建线程处理新的信号。
缺点:系统负荷不大时,这也是个办法。但系统负荷较大时,很可能当前信号的线程占用CPU,导致下一信号也不能被及时处理,从而造成连锁反应。甚至可能系统中线程越来越多,最终崩溃。3、在下一个触发信号到达时,如果当前信号未处理结束则使用TerminateThread强行终止。
这个方法应该能够克服上面的两个缺点,但查了好几天,都说TerminateThread会造成泄漏。《Windows 核心编程》提到,线程函数返回时能够确保:
1.在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
2.操作系统将正确地释放线程堆栈使用的内存。
3.系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
4.系统将递减线程内核对象的使用计数。由于我的线程不会分配内存,所以主要问题应该在“释放线程堆栈”和“递减线程内核对象的使用计数”。我的问题是:
1.确实没有办法TerminateThread后释放线程堆栈吗?
2.TerminateThread后,通过CloseHandle是否可以达到“递减线程内核对象的使用计数”的效果?我觉得我的这个需求在一些需要实时进行产品检测的流水线上是很常见的,应该有比较好的解决办法才对。期望高手给予解答,非常感谢!分不够了,惭愧
解决方案 »
- MFC中,分辨率改变后,如何让窗体上的控件大小,位置按比例改变
- xerces自带例子的疑惑:CreateDOMDocument生成的xml用MemParse不能解析?
- GetModuleHandle(0)的真正意思?
- 怎么实现自动打开一个别的程序,并且自动点击其中的按纽?
- 一个关于链接的问题
- CListCtrl如何实现双击选中一行,弹出设置,以及打印该行功能?
- 在数据库(Access)编程中录入文本数据的莫名出错提示!
- 用一个.bmp文件作为对话框的背景,想用BitBlt,其中的pSrcDC指针怎样设置?
- 奇怪了!为什么我的位图资源不能读出来?! :(
- 硬盘被拔出了,如何让ReadFile WriteFile快速返回报错
- VC对数据库的访问中,哪种技术是最常用的
- 复制 CListCtrl 的内容
假如当前正在处理信号A:
突然很短时间内连续出现了信号B,C,D,E;
当前时刻,只要停掉处理A,开始处理信号E,就可以了;而B,C,D信号没有必要处理的;
另外,启动线程有一定开销的,所以能否只用一个线程来处理;在线程内部,利用几个类似状态的
变量,如:
CurrentState;//当前最后到达的信号状态
ActiveState ; //正在进行计算的信号状态;
UINT ThreadFunc(LPVOID pParam)
{
...
while(TRUE)
{
//获取CurrentState
CurrentState = GetCurrentState();
if (ActiveState != CurrentState)
{
//清理ActiveState状态的资源;
ReleaseState(ActiveState);
//切换当前状态未活动状态
ActiveState = CurrentState;
}
switch(ActiveState)
{
case SignalA:
{
//进行SignalA运算
switch(ActiveState->m_nStep)
{
case 1:
//运算步骤1
...
ActiveState->m_nStep++;
break;
case 2:
//运算步骤2
... break;
...
} }
break;
case SignalB:
{
//进行SignalB运算
...
}
break;
case SignalC:
{
//进行SignalC运算
...
}
break;
...
}
}
}
非常感谢!应该是个不错的方法。具体如何实现还得多学习学习。我找到下面这个帖子:
http://topic.csdn.net/t/20030312/21/1523636.html
应该是使用这种方法吧?
看23楼的意思,应该是可以不用抛出异常,让线程正常结束的。不过我调试的时候,还是出现异常了。有时多加个printf打印信息,异常就没了,看样子还是有问题。不知道这方面有没有更好的资料可以学习的?
(或者你说的是,来5个,有5个处理位,然后一次发送5个信号,创建5个线程?)另外,你处理时的算法如何,在各种极端情况下,一般都是多少毫秒处理完。
[单个线程耗时] [多个线程并发耗时] 各种指标综合分析。
PS: 要不你可以弄一个worker线程,专门负责申请空间,然后再这个线程内创建 Processor线程,把各种空间都传递过去,保证Processor线程连栈变量都不用,这样 TerminateThread 应该会安全点吧。这样,负责外部中断的就交给 worker线程咯。PS: 我估计,负责传送产品的系统与你现在开发的系统是完完全全的两个,不然就可以:处理完当前的,才传递下一个。
{ HANDLE hThread;CONTEXT context;
hThread = CreateThread(NULL,
0,
threadFunc,
0,0,
0);
while(1)
{
getch();
SuspendThread(hThread);
context.ContextFlags=CONTEXT_CONTROL;
GetThreadContext(hThread,&context);
context.EFlags|=0x100;
SetThreadContext(hThread,&context);
ResumeThread(hThread);
}
return 0;
}DWORD WINAPI threadFunc(LPVOID pParam)
{
d:
__try
{
while(1)SwitchToThread();
}__except(EXCEPTION_EXECUTE_HANDLER)
{
cout<<"sdf"<<endl;
goto d;
}
return 0;
}
非常感谢列宁同志!测试确实可以!另外受列宁同志启发,我稍微修改了一下,主要思路是在线程创建时传入CREATE_SUSPENDED,创建完后立即用CONTEXT_FULL获得线程的CONTEXT,那么以后就可以随时SetThreadContext回到线程函数的第一条代码,只要在这里加一个条件判断退出线程,就相当于能够随时退出线程,这样连异常也不要了!启动线程:
hand = CreateThread(NULL,0,TestThread,¶m,CREATE_SUSPENDED,NULL);
Context.ContextFlags = CONTEXT_FULL;
GetThreadContext(hand,&Context);
ResumeThread(hand);回到线程函数的第一条代码:
SuspendThread(hand);
SetThreadContext(hand,&Context);
ResumeThread(hand);