这个问题已经困扰了一年了...问题是这样的,
写一个函数,在该函数内创建一个线程,并在线程里创建一个httprio对象,使用该对象调用一个webservices的耗时10秒的方法
在窗体上添加一个按钮,在点击该按钮时调用上面说的这个函数,调用的情况非常诡异...
首先连续点击该按钮5次,这5次调用会各自阻塞10秒后返回,然后再点击5次按钮,第一次会在10秒返回,第二次是20秒,第三次是30秒....,好像调用被串列化了,而且之后都是这样,再也恢复不到第一次的状况了,
以下是在调用时的状况Start... 0
Start... 1
Start... 2
Start... 3
Start... 4
10187  0
10031  1
10031  2
10031  3
10032  4
Start... 5
Start... 6
Start... 7
Start... 8
Start... 9
10016  5
19547  8
30109  6
40047  7
50078  9肯定不是服务端的问题,因为用.net c#实现的客户端一样的调用每次都是10秒就返回了
应该也不是版本的问题,在delphi7和delphi2010中都是这样请教众位,这个问题该怎么解决?

解决方案 »

  1.   

    晚上把代码贴出来吧,应该不是线程的问题,如果线程有问题第一次也会阻塞的,顺便问一下有没httprio的替代品?
      

  2.   

    这个是实现的独立线程执行的类unit SingleThreadTask;interfaceuses SysUtils, Classes, ExtCtrls;type
      TProcessTaskCallBack = procedure of Object;
      TProcessTaskCallBack2 = procedure (obj: TThread) of Object;
      //独立线程过程
      TSingleThreadTask = class(TThread)
      private
        CallBack: TProcessTaskCallBack;
        CallBack2: TProcessTaskCallBack2;
      protected
        procedure Execute; override;
      public
        //输出函数
        class procedure ProcessTask(CallBack: TProcessTaskCallBack); overload;
        class function ProcessTask(CallBack: TProcessTaskCallBack2): TThread; overload;
      end;implementation//执行过程
    class procedure TSingleThreadTask.ProcessTask
    (
      CallBack: TProcessTaskCallBack
    );
    var
      obj: TSingleThreadTask;
    begin
      obj := TSingleThreadTask.Create(true);
      obj.CallBack := CallBack;
      obj.Resume;
    end;
    //执行过程
    class function TSingleThreadTask.ProcessTask
    (
      CallBack: TProcessTaskCallBack2
    ): TThread;
    var
      obj: TSingleThreadTask;
    begin
      obj := TSingleThreadTask.Create(true);
      obj.CallBack2 := CallBack;
      obj.Resume;
      Result := obj;
    end;
    //
    procedure TSingleThreadTask.Execute;
    begin
      //执行任务
      try
        if Assigned(self.CallBack) then
          self.CallBack
        else if Assigned(self.CallBack2) then
          self.CallBack2(self);
      finally
        //自释放
        self.Free;
      end;
    end;end.这个是窗体那个文件unit fmMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, activex,
      Dialogs, InvokeRegistry, Rio, SOAPHTTPClient, StdCtrls, SOAPHTTPTrans, WinINet;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        nMax: Integer;
        procedure SlowCall(thread: TThread);
        procedure HTTPRIOBeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses WSBasic, SingleThreadTask;{$R *.dfm}
    procedure TForm1.HTTPRIOBeforePost
    (
      const HTTPReqResp:
      THTTPReqResp; Data: Pointer
    );
    var
      TimeOut,TimeOut2 : integer;
    begin
      TimeOut := 15 * 1000;
      TimeOut2 := 30 * 1000;
      if TimeOut > 0 then
        InternetSetOption(Data, INTERNET_OPTION_CONTROL_SEND_TIMEOUT, Pointer(@TimeOut), SizeOf(TimeOut));
      if TimeOut2 > 0 then
        InternetSetOption(Data, INTERNET_OPTION_RECEIVE_TIMEOUT, Pointer(@TimeOut2), SizeOf(TimeOut2));
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      TSingleThreadTask.ProcessTask(self.SlowCall);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      self.nMax := 0;
    end;procedure TForm1.SlowCall(thread: TThread);
    var
      ts: TTimeStamp;
      n: Integer;
      s: String;
      prio: THTTPRIO;
      nID: Integer;
    begin
      //thread.Priority := tpIdle;
      nID := self.nMax;
      self.nMax := self.nMax + 1;
      CoInitialize(nil);
      try
        self.Memo1.Lines.Add(format('Start... %d', [nID]));
        ts := DateTimeToTimeStamp(Now);
        try
          prio := THTTPRIO.Create(self);
          try
            //prio.HTTPWebNode.OnBeforePost := self.HTTPRIOBeforePost;
            prio.URL := 'http://.../JTMISWebService/WSBasic.asmx';
            //prio.HTTPWebNode.ReceiveTimeout := 20 * 1000;
            (prio as WSBasicSoap).CommonRemoteCall(120, 'test_Longtimeobstruct2', format('SecCount=10; ID=%d', [nID]));
          finally
          begin
            prio.HTTPWebNode.Free;
            prio.Free;
          end;
          end;
          s := ''
        except on ex: Exception do
          s := 'x ' + ex.Message;
        end;
        n := DateTimeToTimeStamp(Now).Time - ts.Time;
        //ShowMessage(intToStr(n) + ' ' + s);
        self.Memo1.Lines.Add(intToStr(n) + ' ' + s + ' ' + IntToStr(nID));
      finally
        CoUnInitialize;
      end;
      //
      EndThread(0);
    end;end.代码就是这么简单,感觉是delphi的一个特性,不过实在想不通为什么一开始可以只要第一个调用返回之后就不行了,现在不敢报什么指望,只想找一个没有这种毛病的替代控件