一个关于线程的小问题(10000分都行)
示意图如下:
我在客户端生成一个线程Thread连接到服务器和服务器交换数据。我在主程序的一个函数中向服务器发送了一个请求,函数这个时候Sleep,等待运行结果,服务器端处理后返回数据到客户端,由线程接收到数据,写入到缓冲区。函数这时取缓冲区数据。但是程序运行不成功。
我设置断点执行后发现,实际上运行的过程是客户端等待主进程的函数执行完成后,才执行的线程接收代码。不知道为什么,这种问题不知道怎么解决。请各位帮帮忙。不胜感激!
像这样的:
客户端 服务器
|--Thread----------------------Thread
|--Function----------------------|
问题点数:100、回复次数:14Top
1 楼leonatcs(LeonKennedy)(时常逛一逛csdn,有益身心健康。)回复于 2005-06-01 22:23:50 得分 5
那只能是你没有在合适的时候启动线程了。Top
2 楼xpdavis(咕嘟-不想孤独)回复于 2005-06-01 22:53:40 得分 5
最好还是给出代码好找出错误Top
3 楼jemyzhang(妙狐)回复于 2005-06-02 00:27:09 得分 5
可以在主进程中进入循环,判断数据是否收到,如果收到再退出循环。
不知可否解决问题Top
4 楼chiengod(钱神爷)回复于 2005-06-02 08:28:11 得分 5
那就不要用Sleep了,发送请求后启动线程,不断的判断、读缓冲区。Top
5 楼constantine(飘遥的安吉儿)回复于 2005-06-02 08:46:27 得分 5
看代码吧,还有不是说主线程执行后才执行什么的....
如果这样还叫多线程..Top
6 楼songhtao(三十年孤独)回复于 2005-06-02 08:57:26 得分 5
主要还是要看代码,给你个例子参考:http://www.pcbookcn.com/article/2333.htm
Top
7 楼jim2001999(乐天)回复于 2005-06-02 09:23:47 得分 0
谢谢楼上的高手。简化的错误关键代码如下:
我先通过点Button1连接到服务器。然后线程一直监视数据到来。然后点Button4,服务器处理后返回"bb",但始终是打印的是There error,运行顺序是先把Button4Click运行完毕后,再运行的ClientThread的ReadStr(buf)。请各位高手帮忙!!!谢谢。
ClientThread.cpp
//---------------------------------------------------------------------------
// 客户收受线程
#include <vcl.h>
#pragma hdrstop
#include "ClientUnit1.h"
#include "ClientThread.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TClientThread::TClientThread(bool CreateSuspended,
TClientWinSocket * ASocket):TThread(CreateSuspended)
{
FreeOnTerminate=true; // 线程中止后释放线程
ClientSocket=ASocket;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::Execute()
{
char buf[1024+1];
pStream=new TWinSocketStream(ClientSocket,0x7fffffff);
while(!Terminated && ClientSocket->Connected)
if (ReadStr(buf)>0)
{
Message=buf;
Synchronize(MemoAdd);
strcpy(Form1->array,buf);
}
else
ClientSocket->Close(); // 返回的串长为0表示已断开
delete pStream;
Message="已与服务器断开连接...";
Synchronize(MemoAdd);
}
//---------------------------------------------------------------------------
int __fastcall TClientThread::ReadStr(char * buf) //接收数据
{
int Len=0;
pStream->WaitForData(0x7fffffff); // 等待到有串或断开
if (pStream->WaitForData(10000)) // 第二次为假表示断开
Len=pStream->Read(buf,1024);
// ClientSocket关闭后,pStream->Read()会产生异常,所以要判定或try
buf[Len]=0;
return Len;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::MemoAdd() //将数据加入Memo1中
{
Form1->Memo1->Lines->Add(Message); // Synchronize(MemoAdd);
}
//---------------------------------------------------------------------------
ClientUnit1.cpp
/*
BCB-Socket阻塞模式通讯测试-客户端
*/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ClientThread.h"
#include "ClientUnit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String IP=Edit1->Text.Trim();
if (IP!="")
if (!ClientSocket1->Active)
{
ClientSocket1->Address=IP;
ClientSocket1->Port=Edit3->Text.ToInt();
try
{
ClientSocket1->Open();
Memo1->Lines->Add("已连接到:"+
IP+":"+ClientSocket1->Port);
Memo1->Lines->Add("本机IP:"+
ClientSocket1->Socket->LocalAddress+
":"+ClientSocket1->Socket->LocalPort);
TClientThread *thread=
new TClientThread(false,ClientSocket1->Socket);
}
catch(...)
{
Memo1->Lines->Add("连接失败");
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ClientSocket1->Socket->SendText(Edit2->Text);
Edit2->Text="";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
ClientSocket1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
ClientSocket1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Error(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
ErrorCode=0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
this->ClientSocket1->Socket->SendText("aa");
::Sleep(1000);
if(String(array) == "bb")
{
this->Memo1->Lines->Add("there ok!!!!");
}
else
{
this->Memo1->Lines->Add("there error!!!!");
}
}
//---------------------------------------------------------------------------
Top
8 楼lidawen(Darwin)回复于 2005-06-02 09:41:16 得分 3
upTop
9 楼jim2001999(乐天)回复于 2005-06-02 11:43:13 得分 0
顶下。。。
各位高手。帮忙啊。我的毕业设计的大问题就靠你们了。。!!!!!不胜感激啊!Top
10 楼jim2001999(乐天)回复于 2005-06-02 21:02:50 得分 0
顶啊!!!Top
11 楼xpdavis(咕嘟-不想孤独)回复于 2005-06-02 23:04:38 得分 60
程序没问题,不过设计的不好,回头给你一个好点的设计Top
12 楼xpdavis(咕嘟-不想孤独)回复于 2005-06-03 08:39:21 得分 0
简单的说,这个设计最大的缺陷在于主线程必须等待一个固定的时间(可能很长),以确定数据已经接收到。这样的设计反应太迟钝了,其实只要在SOCKET线程收到数据时发送消息(COPY DATA消息)给主线程,主线程只要做好消息映射就可以了,这样就可以驱动TForm1的一个方法将收到的数据显示出来。
另外,楼主的设计有点混乱,2个单元文件互相包含,一般而言这种做法是不可取的。Top
13 楼flyback(墨羽)回复于 2005-06-03 08:46:48 得分 7
一开始就应该启动线程,但是必须让它等待一个主程序的完成标志
global boolean g_bIsOk
main()
{
createthread (abc)
abc.run
...
...
g_bIsOk = true
}
abc()
{
if(g_bIsOk == true)
{
...
}
else
{
sleep(...)
}
}Top
14 楼jim2001999(乐天)回复于 2005-06-03 09:36:36 得分 0
to:xpdavis(咕嘟),你好。我的邮箱是:jim2001999@163.com 发点代码谢谢了。Top




