PDA

View Full Version : سوال: آیا امکان ارسال ReplyStatus حاصل ازIdICMP هز طریق SendMessage وجود دارد؟



hp1361
دوشنبه 23 آبان 1390, 18:25 عصر
باسلام.

من در برنامه ام هر ثانیه یک Thread میسازم و درون اون عمل Ping رو انجام میدم.بعد نتیجه Ping رو که بصورت کلاس RplayStatus هستش رو با کد زیر ارسال میکنم :


SendMessage(frm_Main.Handle,WM_MyMessage,Integer(R eplayStatus),0);


اما در Thread اصلی برنامه وقتی فیلد ToIpAddress رو استفاده میکنم اون چیزی نیست که انتظا دارم!مشکل کارم کجاست؟آیا طریقه Casting ام اشتباست؟آیا ReplayStatus برای همه Thread که میسازم مشترکه و به همین خاطر فیلد ها قاطی میشه؟
مشکل کجاست؟

Felony
دوشنبه 23 آبان 1390, 19:05 عصر
با اون یک خط کد که قرار دادی میخوای مشکل Thread ت رو بهت بگیم ؟! این هزار بار ، سوالاتون رو به صورت کامل و با نمونه کدی که مینویسید قرار بدید .

hp1361
سه شنبه 08 آذر 1390, 15:54 عصر
سلام

این کد مورد استفاده منه.

اینترنت رو قطع کنید و چند تا سایتذو ای پی بهش بدید.ای پی لوکال رو هم بدید.و نتیجه رو ببینید.برای همه 1024 مقدار بازگشتی رو مینویسه


unit fMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, IdBaseComponent, IdComponent, IdRawBase,
IdRawClient, IdIcmpClient;

type
TfrmMain = class(TForm)
gbMustPing: TGroupBox;
gbOther: TGroupBox;
lblReplayStatus: TLabel;
lbReplayStatus: TListBox;
btnPing: TButton;
lbIPList: TListBox;
lblIPList: TLabel;
btnAddIP: TButton;
IdIcmpClient1: TIdIcmpClient;
procedure btnPingClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnAddIPClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure WNDProc(var Mess: TMessage); Override;
end;

type
TPinger = class(TThread)
constructor Create(const IP: String);
protected
fIPMustPing: string;
procedure Execute; override;
end;

var
frmMain: TfrmMain;
WM_PingArrived: Dword;

implementation

{$R *.dfm}

procedure TfrmMain.WNDProc(var Mess: TMessage);
begin
if Mess.Msg = WM_PingArrived then
lbReplayStatus.Items.Add(Format('IP : %s - Bytes Received : %s',
[String(Mess.WParam), string(Mess.LParam)]))
else
inherited;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
// Set WM_PingArrived
WM_PingArrived := RegisterWindowMessage('WM_PingArrived');
end;

procedure TfrmMain.btnAddIPClick(Sender: TObject);
var
IPAddr: string;
begin
IPAddr := InputBox('', 'Enter IP address or name of a site :', '127.0.0.1');
lbIPList.Items.Add(IPAddr);
end;

procedure TfrmMain.btnPingClick(Sender: TObject);
var
Pinger: Array of TPinger;
IPNO: Integer;
begin
lbReplayStatus.Clear;
SetLength(Pinger, lbIPList.Items.Count);
for IPNO := 0 to lbIPList.Items.Count - 1 do
begin
Pinger[IPNO] := TPinger.Create(lbIPList.Items.Strings[IPNO]);
Pinger[IPNO].FreeOnTerminate := True;
Pinger[IPNO].Start;
end;
end;



{ TPinger }

constructor TPinger.Create(const IP: String);
begin
inherited Create(True);
fIPMustPing := IP;
end;

procedure TPinger.Execute;
var
Bytes: string;
begin
with TIdIcmpClient.Create(frmMain) do
try
PacketSize := 1024;
ReceiveTimeout := 5000;
Host := fIPMustPing;
Ping;
Bytes := IntToStr(ReplyStatus.BytesReceived);
SendMessage(frmMain.Handle, WM_PingArrived, Integer(fIPMustPing), Integer(Bytes));
finally
Free;
end;
end;

end.

vcldeveloper
سه شنبه 08 آذر 1390, 22:05 عصر
من در برنامه ام هر ثانیه یک Thread میسازم
چه خبره مگه؟!! Multi-thread کار کردن این نیست که برای هر کار موازی یک Thread بسازید! ایجاد Thread سربار زیادی داره، بخصوص در فواصل زمانی کم. با این کار شما نه تنها کارایی برنامه خودتون رو بالا نمی برید، بلکه باعث کاهش کارایی برنامه و کاهش بیهوده منابع سیستم میشید! اگر میخواید تعداد زیادی سایت رو پینگ کنید، راهش این نیست که برای هر کدوم یک Thread بسازید. گیرم کاربر خواست 1000 تا سایت رو پینگ کنه، شما میرید 1000 تا Thread می سازید؟!

شما باید یک Thread Pool با تعدادی Thread محدود داشته باشید (مثلا تعداد Thread میتونه این باشه؛ هسته های پردازشی موجود ضرب در 4، چون این Thread های شما در عمل توان پردازشی بالایی نمیخوان، و اکثر وقت شان صرف انتظار برای رسیدن پیام از سرور میشه) . کارها باید بین این تعداد Thread محدود تقسیم بشه. می تونید یک Blocking Queue ورودی داشته باشید، یک Blocking Queue خروجی و یک Thread Pool به عنوان consumer لیست ورودی. در حالت عادی Thread Pool منتظر میمونه که مقداری به لیست ورودی اضافه بشه. هر زمان که مقداری در لیست ورودی باشه، این مقدار به یکی از Thread های موجود در Pool داده میشه تا عملیات مورد نظر را روی اون انجام بده. هر Thread هم مقدار خروجی خودش رو در لیست خروجی ثبت میکنه. یک Thread میتونه منتظر لیست خروجی باشه، و هر زمان که مقداری وارد لیست خروجی شد، Thread اصلی رو خبر کنه، تا Thread اصلی عملیات مربوط به خودش رو انجام بده. البته پیاده سازی اصولی و درست همه این چیزها کار ساده ایی نیست، پس بهتره از کتابخانه های موجود مثل OmniThread برای همچین کارهایی استفاده کنید.

در ضمن، به جای اینکه از SendMessage و string به اون شکل استفاده کنید، از PostMessage استفاده کنید، و اون مقدار Bytes رو هم مستقیما به صورت Integer ارسال کنید. البته قبلش چک کنید که واقعا مقادیر دریافتی شما از پینگ درست باشه، شاید در اون کد مشکل دارید، و مقدار خروجی پینگ شما با اون کد واقعا همیشه 1024 هست.

hp1361
شنبه 12 آذر 1390, 12:12 عصر
سلام

اقای کشاورز اگه ممکنه در مورد مطالبی که فرمودید مثالی لینکی اموزشی چیزی معرفی کنید ممنون میشم.

vcldeveloper
شنبه 12 آذر 1390, 23:07 عصر
http://www.thedelphigeek.com/2011/10/omnithreadlibrary-in-practice-1web.html

hp1361
یک شنبه 20 آذر 1390, 15:20 عصر
با عرض سلام مجدد

آقای کشاورز:بعد از مدتی مطالعه مطالب لینک بالا و موارد مربوط به ان با کد زیر روبرو شدم.در کد زیر با کلمه Delegate روبرو شدم.واستم ببینم آیا این همان ی است که در#C استفاده میشد؟



OtlTaskControl.CreateTask(TomniTaskDelegate,string )Method
Declared in otlTaskControl
Parameters
worker
otlTask.TomniTaskDelegate
taskname
System.string
Returns
otlTaskControl.IomniTaskControl


ممنون

vcldeveloper
دوشنبه 21 آذر 1390, 22:07 عصر
آقای کشاورز:بعد از مدتی مطالعه مطالب لینک بالا و موارد مربوط به ان با کد زیر روبرو شدم.در کد زیر با کلمه Delegate روبرو شدم.واستم ببینم آیا این همان ی است که در#C استفاده میشد؟
TOmniTaskDelegate یک Anonymous Method هست که در CreateTask حاوی کد قابل اجرا برای اون Task خواهد بود.

نیازی نیست که شما با کلاس های سطح پایین اون کتابخانه کار کنید. بهتر هست با کلاس های سطح بالای آن که در OtlParellel.pas تعریف شدند، استفاده کنید.