紧急求救:为什么我的串口通讯发送比较大的数据包时系统的其它操作没反应呢?(有代码)

ManOfBCB 2006-06-15 08:46:29
我的代码如下:

OVERLAPPED OSWrite;
memset( &OSWrite, 0, sizeof(OVERLAPPED));
OSWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if( OSWrite.hEvent == NULL ) return false;

COMSTAT comstat;
DWORD error_flags;
// 清除通讯错误
ClearCommError(ComHandle,&error_flags,&comstat);
if( error_flags > 0 )
{
// 清除发送缓冲区
PurgeComm(ComHandle,PURGE_TXABORT | PURGE_TXCLEAR) ;
}
unsigned long count=0,res=0;
bool bError = true;
bool status = WriteFile(ComHandle,buffer,length,&count,&OSWrite);
if( !status )
{
DWORD dwError = GetLastError();
if( dwError == ERROR_IO_PENDING )
{
// dwError = 995:由于线程退出或应用程序请求,已放弃 I/O 操作。
// 997:重叠 I/O 操作在进行中。
//if( dwError != 997 && dwError != 995 )
//{
// AnsiString strErr = "";
//}
while( dwError != 995 && !GetOverlappedResult( ComHandle,&OSWrite, &count, true ) )
{
dwError = GetLastError();
if( dwError == ERROR_IO_INCOMPLETE )
{
res += count;
continue;
}
else
{
bError = true;
}
Sleep(1);
Application->ProcessMessages();
}
res += count;
bError = (unsigned)length != res;
}
else
{
bError = true;
}
}
CloseHandle(OSWrite.hEvent);

return !bError;

这是我的发送函数,我发送和接收缓冲区设置成20480,数据包最大长度20k,大家帮帮忙吧!非常感谢,
我的接收是用消息通知读取数据的。

非常感谢
...全文
867 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
FongLuo 2006-09-24
  • 打赏
  • 举报
回复
串口发送数据时比较慢的。所以在驱动程序内部都有缓冲区。即使使用了重叠操作在发送大数据时也是很慢。在等待重叠事件时也是存在延时的。要想程序快速响应,只有使用多线程。主程序把数据往线程中一丢,就可以处理其它的事件了。当然,在同步方面有很多办法的。根据不同的需要使用不同的方法。不能套用同一个。
Andrionda 2006-09-19
  • 打赏
  • 举报
回复
xifenmin 谢谢 能传一份吗? plyat@163.com
ManOfBCB 2006-09-17
  • 打赏
  • 举报
回复
up
dongsheng10101 2006-09-06
  • 打赏
  • 举报
回复
xifenmin(dtxi) ( ) "我写一个后台线程接收数据(异步)的串口,有需要的吗?"
你好,能发一个给我吗?谢谢.
email:dongsheng10101@163.com
ManOfBCB 2006-06-27
  • 打赏
  • 举报
回复
up
ManOfBCB 2006-06-25
  • 打赏
  • 举报
回复
请问采用多线程同步通讯是否效率要高些,不会影响主线程鼠标操作?
ManOfBCB 2006-06-24
  • 打赏
  • 举报
回复
1、能不能发给我学习一下?谢谢!Toyan@tom.com
2、主要还是发送数据;
xifenmin 2006-06-23
  • 打赏
  • 举报
回复
我写一个后台线程接收数据(异步)的串口,有需要的吗?
「已注销」 2006-06-23
  • 打赏
  • 举报
回复
关注...
「已注销」 2006-06-23
  • 打赏
  • 举报
回复
关注...
ManOfBCB 2006-06-22
  • 打赏
  • 举报
回复
up
ManOfBCB 2006-06-21
  • 打赏
  • 举报
回复
大家帮忙看看,好像没有效果,还是在发送的时候,鼠标不能动,定时器也没动.
ManOfBCB 2006-06-21
  • 打赏
  • 举报
回复
我的线程发送:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "SendData.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TSendData::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------

__fastcall TSendData::TSendData( HANDLE com_handle,
unsigned char* sendbuf, long sendlen, bool CreateSuspended )
: TThread(false)
{
ComHandle = com_handle;
length = sendlen;
buffer = new unsigned char[length+10];
memset( buffer, 0, length+10 );
memcpy( buffer, sendbuf, length );
}
//---------------------------------------------------------------------------

__fastcall TSendData::~TSendData()
{
if ( buffer )
{
delete []buffer; buffer=0;
}
}

void __fastcall TSendData::Execute()
{
while ( !Terminated )
{
Synchronize( SendToCom );
Sleep(1); // 停止1毫秒
Application->ProcessMessages();
}
}
//---------------------------------------------------------------------------

void __fastcall TSendData::SendToCom( )
{
// 是否写事件存在
// 没有安全属性,手工重置事件,初始状态:无信号,没有名字
// 标识事件,数据传送完成时,将它设为信号状态

OVERLAPPED OSWrite;
memset( &OSWrite, 0, sizeof(OVERLAPPED));
OSWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if( OSWrite.hEvent == NULL )
{
this->Terminate(); // 关闭线程
}

COMSTAT comstat;
DWORD error_flags;
// 清除通讯错误
ClearCommError(ComHandle,&error_flags,&comstat);
if( error_flags > 0 )
{
// 清除发送缓冲区
PurgeComm(ComHandle,PURGE_TXABORT | PURGE_TXCLEAR) ;
}
unsigned long count=0,res=0;
bool bError = true;
bool status = WriteFile(ComHandle,buffer,length,&count,&OSWrite);
if( !status )
{
DWORD dwError = GetLastError();
if( dwError == ERROR_IO_PENDING )
{
// dwError = 995:由于线程退出或应用程序请求,已放弃 I/O 操作。
// 997:重叠 I/O 操作在进行中。
//if( dwError != 997 && dwError != 995 )
//{
// AnsiString strErr = "";
//}
while( dwError != 995 && !GetOverlappedResult( ComHandle,&OSWrite, &count, true ) )
{
dwError = GetLastError();
if( dwError == ERROR_IO_INCOMPLETE )
{
res += count;
continue;
}
else
{
bError = true;
}
Sleep(1);
//Application->ProcessMessages();
}
res += count;
bError = (unsigned)length != res;
}
else
{
bError = true;
}
}
CloseHandle(OSWrite.hEvent);

this->Terminate(); // 关闭线程
}

大伙给看看没啥问题吧?主要是发送完后线程自动关闭
ManOfBCB 2006-06-21
  • 打赏
  • 举报
回复
我的类是自己做的,线程后台监控串口通知主线程接收数据,采用的是异步无阻塞
方式,用了事件,发送的时候咋这么慢呢?特别是大数据发送(其实也就几k),请大
家帮忙给分析一下!谢谢

我在网上下的串口通讯程序和我做的都有点不一样,但是原理好像还是一样的,
为什么我的会这样呢?大家又没有遇到过?有没有解决的办法?谢谢

9527 2006-06-21
  • 打赏
  • 举报
回复
曾经down了一个微软的串口操作的例子,我使用了效果还可以,下面是串口操作部分,由于使用了一些自定义结构,应该无法直接拷贝使用,仅供参考:

/*-----------------------------------------------------------------------------

FUNCTION: WriterGeneric(char *, DWORD)

PURPOSE: Handles sending all types of data

PARAMETER:
lpBuf - pointer to data buffer
dwToWrite - size of buffer

HISTORY: Date: Author: Comment:
10/27/95 AllenD Wrote it

-----------------------------------------------------------------------------*/
DWORD CSerialCom::WriterGeneric(char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
HANDLE hArray[2];
DWORD dwWritten;
DWORD dwRes;

//
// If no writing is allowed, then just return
//
if (NOWRITING(COMInfo))
return -1;

//
// create this writes overlapped structure hEvent
//
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
printf_log("CreateEvent (overlapped write hEvent)\n");

hArray[0] = osWrite.hEvent;
hArray[1] = ghThreadWriteOverEvent;//其实没有使用

//
// issue write
//
if (!WriteFile(COMDEV(COMInfo), lpBuf, dwToWrite, &dwWritten, &osWrite)) {
if (GetLastError() == ERROR_IO_PENDING) {
//
// write is delayed
//
dwRes = WaitForMultipleObjects(2, hArray, FALSE, WRITE_CHECK_TIMEOUT);
switch(dwRes)
{
case WAIT_OBJECT_0:
SetLastError(ERROR_SUCCESS);
if (!GetOverlappedResult(COMDEV(COMInfo), &osWrite, &dwWritten, FALSE)) {
if (GetLastError() == ERROR_OPERATION_ABORTED)
printf_log("Write aborted\r\n");
else
printf_log("GetOverlappedResult(in Writer)\n");
//ShowLastError("Write:GetOverlappedResult");
CheckComStat(TRUE);
}

if (dwWritten != dwToWrite) {
if (GetLastError() == ERROR_SUCCESS)
printf_log("Write timed out. (overlapped)\r\n");
else
printf_log("Error writing data to port (overlapped)\n");
}
break;

//
// thread exit event set
//
case WAIT_OBJECT_0 + 1:
break;

//
// wait timed out
//
case WAIT_TIMEOUT:
printf_log("Wait Timeout in WriterGeneric.\r\n");
break;

case WAIT_FAILED:
default: printf_log("WaitForMultipleObjects (WriterGeneric)\n");
break;
}
}
else
//
// writefile failed, but it isn't delayed
//
printf_log("WriteFile (in Writer)\n");
}
else {
//
// writefile returned immediately
//
if (dwWritten != dwToWrite)
printf_log("Write timed out. (immediate)\r\n");
}

CloseHandle(osWrite.hEvent);

return dwWritten;
}
ManOfBCB 2006-06-17
  • 打赏
  • 举报
回复
谢谢,我试试
BenLeak 2006-06-16
  • 打赏
  • 举报
回复
放到线程中,必须 Sleep(1)
不需要 Application->ProcessMessages();
ManOfBCB 2006-06-16
  • 打赏
  • 举报
回复
加入线程后,是否需要Sleep(1);
Application->ProcessMessages();
?谢谢
gyj_china 2006-06-15
  • 打赏
  • 举报
回复
你把它封装成线程,看看效果是否有改善,因为循加了Application->ProcessMessages();也不一定能及时相应操作指令。
ManOfBCB 2006-06-15
  • 打赏
  • 举报
回复
除了封装成线程,没有别的办法了吗?

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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