procedure TForm1.Button1Click(Sender: TObject);
var
sListen,sClient:tsocket;
local:sockaddr_in;
client:PSockAddr;
wsadata:twsadata;
namelen:Pinteger;
dwThreadId:DWORD;
fd_read  : TFDSet;
timeout  : TTimeVal;
i:integer;
begin
if wsastartup($0101,wsadata)<>0 then
begin
showmessage('WINSOCK 处始化失败');
exit;
end;
sListen:=socket(pf_inet,sock_stream,ipproto_ip);
if sListen=invalid_socket then
begin
showmessage('SOCKET 错误');
exit;
end;
local.sin_family:=pf_inet;
local.sin_port:=htons(strtoint(trim('18800')));
local.sin_addr.S_addr:=inet_addr(pchar(trim('127.0.0.1')));
bind(sListen,local,sizeof(local));
listen(sListen,5);
 new(client);
new(namelen);
namelen^:=sizeof(client^);
//while (not self.Terminated)  shutdown( sListen, SD_BOTH );
  closesocket( sListen );
while true do
  begin    FD_ZERO( fd_read );
    FD_SET( sListen, fd_read );
    timeout.tv_sec  := 0;
    timeout.tv_usec := 0;
    if select( 0, @fd_read, nil, nil, @timeout ) > 0 then 
    begin
      if FD_ISSET( sListen, fd_read ) then
      begin
        for i:=0 to fd_read.fd_count-1 do //
        begin
          namelen^ := sizeof(client^);
          sClient := accept(sListen,client,namelen);
          if sClient <> INVALID_SOCKET then
          CreateThread(nil,   0,   @ClientThread,  pointer(sClient),   0,   dwThreadId);
             //为sClient创建一个新的线程        end;
      end;
    end;end;点击按钮的时候,程序创建线程和通讯都正常,但是窗体占用CPU达80%,窗体也动不了,
原因是因为不停的在while true do,
请教大侠,怎样做才能使程序运行正常

解决方案 »

  1.   

    sorry,没有看清你的意思,哈哈while   true   do
        begin
            ////我给你加入的部分
            for i := 1 to 100 do begin   //i的范围你可以自己试一下,不用很多,这个也不怎么占时间。
               Application.ProcessMessages;
               //想CPU下降,就再把下面这个加进来,否则就继续掉
               //sleep(10);
            end;
            ////到这里
            FD_ZERO(   fd_read   );
            FD_SET(   sListen,   fd_read   );
            timeout.tv_sec     :=   0;
            timeout.tv_usec   :=   0;
            if   select(   0,   @fd_read,   nil,   nil,   @timeout   )   >   0   then  
            begin
                if   FD_ISSET(   sListen,   fd_read   )   then
                begin
                    for   i:=0   to   fd_read.fd_count-1   do   //
                    begin
                        namelen^   :=   sizeof(client^);
                        sClient   :=   accept(sListen,client,namelen);
                        if   sClient   <>   INVALID_SOCKET   then
                        CreateThread(nil,       0,       @ClientThread,     pointer(sClient),       0,       dwThreadId);
                              //为sClient创建一个新的线程                end;
                end;
            end;
    end; 
      

  2.   

    Application.ProcessMessages; 
    这里是让windows先处理别的在消息队列中的事件的,比如你拖动窗体等等。
    你可以试试看,看是否能达到效果。
      

  3.   

    不是说所有循环都是把资源耗尽的哦,嘿嘿。其实你这里也把while本身就作为一个其他线程来做呀,这样更完美,哈哈。
      

  4.   

    http://topic.csdn.net/u/20071212/16/656d6794-ae0b-471e-87d8-228611b960e2.html
    我的帖子,郁闷了我3天了,还没解呢。
      

  5.   

    while true 部分应该放到一个线程里,要不然窗体会像死机一样, while true跟线程也没什么区别了
    ...
      FD_ZERO(fd_read);
      FD_SET(sListen, fd_read);
      if select(0, @fd_read, nil,nil, nil) > 0 then 
    {
    这里不应该用一个0 timeout的结构,改为0,让这里进入一个阻塞状态
    用于server的socket不像用于通信的client socket会有非法断线一说
    当执行了 closesocket(slisten) 会立即产生 if select(...) = 0
    这时所有的已建立client socket并不会都产生关闭,要代码一个个的去关
    }
    ...
      下面没必要判定FD_ISSET了,只有一个socket, if select(...) > 0 肯定只有slisten发生
    end;
    广告一下, www.sourceforge.net/projects/uvc 是一个socket 1.1兼容组件,开源,欢迎试用,建议