DIOCP任务队列和工作线程

DIOCP任务队列和工作线程

涉及4个单元文件:utils_strings.pas,utils_queues.pas,utils_queueTask.pas,utils_grouptask.pas。

TDQueueTask,只给任务队列开启一个工作线程来执行队列中的任务。

TGroupTask,可以给任务队列指定要开启几个工作线程来执行队列中的任务。

其实,单使用TGroupTask就可以了,可以将TDQueueTask看作是TGroupTask的子集。

大致原理:往队列中提交任务(入队),工作线程从队列中获取任务(出队),通过回调函数来执行任务。

下面上演示代码(DELPHI7测试通过):

/// <author>cxg 2019-6-25</author>

unit Unit1;

interface

uses
  utils_grouptask, utils_queueTask, Windows, Messages, SysUtils, Variants,
  Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TTest = record
    f1: string;
  end;

  PTest = ^TTest;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    task: TDQueueTask;
    task2: TGroupTask;
    procedure callback(pSender: TDQueueTask; pvTaskData: Pointer);
    procedure callback2(pvSender: TGroupTask; pvWorker: TGroupTaskWorker; pvData: Pointer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.callback(pSender: TDQueueTask; pvTaskData: Pointer);
begin
  Caption := PTest(pvTaskData).f1;
  Dispose(pvTaskData);
end;

procedure TForm1.callback2(pvSender: TGroupTask;
  pvWorker: TGroupTaskWorker; pvData: Pointer);
begin
  Caption := PTest(pvData).f1;
  Dispose(pvData);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  p, p2: PTest;
begin
  task := TDQueueTask.Create;
  task.OnExecute := callback;
  New(p);
  p.f1 := '我是一个任务';
  task.PostATask(p);

  task2 := TGroupTask.Create;
  task2.CheckCreateWorker(1);
  task2.OnWorkerExecute := callback2;
  New(p2);
  p2.f1 := '我是二个任务';
  task2.PostATask(p2);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(task);
  FreeAndNil(task2);
end;

end.

  

 

转载于:https://www.cnblogs.com/hnxxcxg/p/11080875.html

Q: 在Diocp中我需要另外开线程去处理逻辑吗? A: 在编码层(TDiocpCoderTcpServer), 逻辑处理事件(OnContextAction), 是由DiocpTask/Qworker(编译开关(QDAC_QWorker)可以进行切换)驱动的,和底层的通信线程是不相干扰。所以在编码层不需要使用另外的线程池,来处理逻辑。 Q: 同一个连接的OnContextAction会同时被多个线程触发吗? A:编码层的OnContextAction是排队处理的,底层接收到数据后交由注册的解码器进行解码, 解码成功后,放到任务队列,然后依次触发OnContextAction,所以同一个连接的OnContextAction同时只会有一个线程调用。 Q: Diocp的断开日志 A: Diocp在DEBUG模式下面会记录详细的日志。会记录每个连接断开的原因。如下 1> xxxx:[2824]投递发送数据请求时出现了错误。错误代码:10054 说明: 这种日志在发送数据的时候系统返回了错误代码,可以根据错误代码(如10054),查询到相应的错误信息。 2> xxxx: [720]响应接收请求时出现了错误。错误代码:64! 说明:这种日志在响应接收请求时系统返回的错误,根据错误代码查询响应的信息。 3> xxxx: [704]接收到0字节的数据,该连接将断开! 说明: 服务端接收到长度为0字节的数据,认为对方关闭了连接。服务端相应的会释放连接触发OnDiscconected函数。 4> xxxx :[812]执行[CheckNextSendRequest::lvRequest.ExecuteSend]失败: 处理投递发送请求数据包时,发现异步关闭请求(Request.Tag = -1)。进行关闭处理! 说明: 这种日志一般在服务端投递了异步关闭请求(PostWSAClose)时,会出现该日志。 上面列举的日志都是正常的,DIOCP只是记录详细情况,以便出现问题时能有据可查,请勿惊慌。 * 中括号[]中的数字是连接对应的SocketHandle,是连接的套接字句柄。 MSDN上面错误代码说明: https://msdn.microsoft.com/en-us/library/ms740668.aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值