呼叫支援~~线程执行正常,但在结束时卡死

hongss 2016-05-25 08:56:44
最近搞一块新采集卡的测试,板卡开发也是摸石头过河的

先上代码(这里我只贴关键代码,显示什么的隐去):
	//启动计数器
int n_Chd_CCD;
Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
int aaa;
do
{
aaa = Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_CCD );
}
while( aaa == 0 );

因为要等待板卡的计数器状态,AC_CRead返回这个状态,0-正在计数,1-计数完成

这段代码,在Timer中运行正常,但,把这段代码放到线程里,
while( 1 )
{
//启动计数器
int n_Chd_CCD;
Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
int aaa;
do
{
aaa = Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_CCD );
}
while( aaa == 0 );
}

执行时,没什么问题,MyThread->Suspended = false;启动,显示什么的都正常,
但是,执行MyTrd->Suspended = true;时,整个程序就卡死了。。。
但,有时候,如果线程执行时间很短的时候(大概几秒),程序又不会卡死。

这是发了什么。。。百撕不得骑姐啊~~~~
...全文
362 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
hongss 2016-05-31
  • 打赏
  • 举报
回复
引用 18 楼 FASM_FASM 的回复:
把你线程中的硬件调用函数,换成sleep来模仿耗时过程。如果整个程序还是挂死,说明是程序线程设计问题。如果没有问题,就说明是你的硬件采集库设计的有问题。
只能这样了
hongss 2016-05-31
  • 打赏
  • 举报
回复
应该是板卡动态库底层的问题了,等他们解决吧,郁闷ing
hongss 2016-05-30
  • 打赏
  • 举报
回复
还有没有大神支招啊?
FASM_FASM 2016-05-30
  • 打赏
  • 举报
回复
把你线程中的硬件调用函数,换成sleep来模仿耗时过程。如果整个程序还是挂死,说明是程序线程设计问题。如果没有问题,就说明是你的硬件采集库设计的有问题。
hongss 2016-05-27
  • 打赏
  • 举报
回复
只采集一个通道,也会出现这个问题。 线程检查,已经处于挂起状态。难道是do...while运行速度过快,导致Form_Main->AC_CRead读取状态处于队列中而卡死?
hongss 2016-05-26
  • 打赏
  • 举报
回复
现在就是不明白,在线程Suspended = true的时候,什么东西还在运行,仅仅就是把
while( 1 )
{
	//启动计数器
	int n_Chd_CCD;
	Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
	Sleep( 1 );
	Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_CCD );
}
改成了
while( 1 )
{
//启动计数器
	int n_Chd_CCD;
	Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
	int aaa;
	do
	{
		aaa = Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_CCD );
	}
	while( aaa == 0 );
}
而已,多了一个do...while循环,就出现这个问题。。。 难道要检查线程阻塞?
FASM_FASM 2016-05-26
  • 打赏
  • 举报
回复
呃,如果这样的话。这个问题应该可以解决。TThread封装的感觉不是太好,因为一旦线程对象创建你基本跟它就失去了联系,除了启动和结束。而且与界面线程的数据通讯效率也比较低下,基本是对windows消息函数的再次封装。推荐你看一下这篇帖子,该帖主对TThread进行了深度改造,基本可以满足灵活的线程间通讯和更强力有效的控制功能。 http://bbs.csdn.net/topics/360040231
hongss 2016-05-26
  • 打赏
  • 举报
回复
16个通道马力全开,无论是这种高占用CPU方式,还是线程方式,都达不到我的采集频率要求。这应该是板卡的硬件问题。 我的信号源频率在380Hz左右,单通道采集,能达到这个水平。而多通道采集时,最高只能达到250Hz左右,两种方式都是这个样子。我看这方面没有什么优化的必要。 现在关键是这个卡死的问题…… 上边不是说,短时间运行线程,停止线程时可以正常停止嘛。经过多次测试,发现这个卡死不光是发生在停止线程时,还有可能发生在开启线程——短暂运行——停止——再启动线程,就卡死了
FASM_FASM 2016-05-26
  • 打赏
  • 举报
回复
这样全放在主线程中也行,但占用率高不是关键啊,关键是即便这样,你的采集频度可以满足吗?我看上面你只采集了一个通道啊。 你试下全通道采集可以满足需求不,如果可以再考虑优化。
hongss 2016-05-26
  • 打赏
  • 举报
回复
应该不是硬件环境的问题。 我试了下,用这样的结构就没问题
		while( 1 )
		{
			if( b_Exit )
			{
				break;
			}
			Application->ProcessMessages();
			MyTrd->GetData();
		}
其中 GetData()就是那个过程
void __fastcall MyThread::GetData()
{
	//启动计数器
	int n_Chd_Data;
	Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
	int aaa;
	do
	{
		aaa = Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_Data);
	}
	while( aaa == 0 );

	Form_Main->n_Count++;
	Form_Main->D_End = GetTickCount();
	if( Form_Main->D_End - Form_Main->D_Begin > 999 )
    {
		Form_Main->RzCB_ReadSpeed->Caption = "读取频率:"+FormatFloat( "0", Form_Main->n_Count * 1000 / ( Form_Main->D_End - Form_Main->D_Begin ) )+" Hz";
        Form_Main->n_Count = 0;
		Form_Main->D_Begin = GetTickCount();
	}

    if( !Form_Main->b_PinLv )
	{
        Form_Main->RzPnl_Count[0]->Caption = "I1 = " + IntToStr( n_Chd_Data);
	}
}
这样的话,就是CPU占用率太高,不是很理想
FASM_FASM 2016-05-25
  • 打赏
  • 举报
回复
引用 2 楼 FASM_FASM 的回复:
你的Timer中的调用和其它板卡函数的调用是序列化的,而线程中用到的Form_Main->h_ACCard这样的资源如果没有同步处理,而本身又不是线程安全的话,出现各种奇怪现象都是正常的。
你上面的代码等于在一个线程中对等待和采集做了序列化处理,当然不会有事。你把AC_CStart和AC_CRead放到不同的线程中就出问题了。看你上面的同步Synchronize( TypeGather );仅仅是对显示界面元素的同步,跟你的板卡采集无关。
hongss 2016-05-25
  • 打赏
  • 举报
回复
引用 2 楼 FASM_FASM 的回复:
你的Timer中的调用和其它板卡函数的调用是序列化的,而线程中用到的Form_Main->h_ACCard这样的资源如果没有同步处理,而本身又不是线程安全的话,出现各种奇怪现象都是正常的。
有关界面的显示等,是进行过同步处理的。 而且,如果不取得计数器状( AC_CRead返回这个状态,0-正在计数,1-计数完成),线程中采用如下代码,也是正常的
	while( 1 )
	{
		for(int i=0; i<16; i++)
		{
			//启动计数器
			Form_Main->AC_CStart( Form_Main->h_ACCard, i, 2 );
		}
		Sleep( 1 );
		for(int i=0; i<16; i++)
		{
			Form_Main->AC_CRead( Form_Main->h_ACCard, i, &n_Chd_Count[i] );
		}

                Synchronize( TypeGather );
这样的采集倒是没什么问题,只是采集频率达不到要求。 修改后,用do...while读取计数器状态后, 采集频率倒是可以达到要求,就是停止线程的时候,会出现程序卡死的状况
FASM_FASM 2016-05-25
  • 打赏
  • 举报
回复
你的Timer中的调用和其它板卡函数的调用是序列化的,而线程中用到的Form_Main->h_ACCard这样的资源如果没有同步处理,而本身又不是线程安全的话,出现各种奇怪现象都是正常的。
hongss 2016-05-25
  • 打赏
  • 举报
回复
补充:Timer中运行正常,但是采集频率太低,达不到要求,所以移到线程中。
FASM_FASM 2016-05-25
  • 打赏
  • 举报
回复
完蛋啊,没有你的硬件环境,不然可以帮你测试一下。
hongss 2016-05-25
  • 打赏
  • 举报
回复
引用 8 楼 FASM_FASM 的回复:
你把Synchronize( TypeGather );去掉看下,是否还卡死。
依然卡死。。。
FASM_FASM 2016-05-25
  • 打赏
  • 举报
回复
你把Synchronize( TypeGather );去掉看下,是否还卡死。
hongss 2016-05-25
  • 打赏
  • 举报
回复
引用 6 楼 FASM_FASM 的回复:
我想问一下,除了主线程(界面线程)以外,你另外就开了这一个工作线程吗?还是每个通道一个线程?
除了主线程,就开了这一个线程。你看上边的代码:
	while( 1 )
	{
		for(int i=0; i<16; i++)
		{
			//启动计数器
			Form_Main->AC_CStart( Form_Main->h_ACCard, i, 2 );
		}
		Sleep( 1 );
		for(int i=0; i<16; i++)
		{
			Form_Main->AC_CRead( Form_Main->h_ACCard, i, &n_Chd_Count[i] );
		}

                Synchronize( TypeGather );
}
这个就是在这个工作线程中,进行初始化及采集十六个通道的过程。
FASM_FASM 2016-05-25
  • 打赏
  • 举报
回复
我想问一下,除了主线程(界面线程)以外,你另外就开了这一个工作线程吗?还是每个通道一个线程?
hongss 2016-05-25
  • 打赏
  • 举报
回复
AC_CStart和AC_CRead就是在同一个线程中的啊 出问题的线程中代码完整的就是我开篇的里边的,不过那只是采集了一个通道,0通道的代码
while( 1 )
{
//启动计数器
	int n_Chd_CCD;
	Form_Main->AC_CStart( Form_Main->h_ACCard, 0, 2 );
	int aaa;
	do
	{
		aaa = Form_Main->AC_CRead( Form_Main->h_ACCard, 0, &n_Chd_CCD );
	}
	while( aaa == 0 );
    Synchronize( TypeGather ); 
}
加上一个do...while就是新开了线程么? 这里的Synchronize( TypeGather );的确只是界面元素同步 整个采集过程是: 1、AC_CStart启动计数器。这个函数会复位计数器的值为0,设置模式,启动计数器开始工作。 2、用AC_CRead函数读出计数器数据,此函数返回计数器停止计数标志。0-正在计数;1-计数完成。 3、若AC_CRead返回1,则结束do...while,进入到下面的显示过程。

1,222

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧