نمایش نتایج 1 تا 17 از 17

نام تاپیک: اختلاف بین تایمر ها در دلفی

  1. #1

    Question اختلاف بین تایمر ها در دلفی

    سلام دوستان گلم
    سوالم را اینطور مطرح می کنم
    بنده بر روی فرمم برای مثال 10 تایمر دارم که هر تایمر یک کار خاصی انجام میده.
    وظیفه ی تایمر 1 اینه که از 1 تا 1000 با فاصله ی زمانی 1 ثانیه شمارش انجام بده و وقتی به 1000 رسید به کاربر پیام بده که 1000 ثانیه است که در برنامه فعال است.
    طی یک سری بررسی ها که داشتم دیدم این تایم متفاوت هستش.
    برای مثال وقتی طی این 1000 ثانیه من با برنامه فعال هستم و در حال کار کردن اگر قرار باشه با توجه به ساعت ویندوز برنامه من ساعت 10:20:20 به من پیام بده بعضی وقتا 10:20:30 یا حتی بعضی وقتا 10:20:55 ثانیه به من پیام داده .این عقب افتادگی زمانی برای چیه ؟ آیا دلیل خاصی داره؟

    سوال دوم بنده هم در خصوص تایمر هست باز
    برای مثال من فرم 4 برنامه خود را گفتم هروقت show شد تایمر 2 فعال بشه و بعد از 10 ثانیه فرم 4 رو hide کنه. این تایمر اکثر مواقع درست کار میکنه اما جدا بعضی وقتا عمل نمیکنه .
    حالا دقیقا نمیدونم چرا ؟ ولی خودم تست کردم و مطمئن شدم مثلا از 100 بار 1 بار این عمل نمیکنه. واقعا دلیل این موضوع چیه ؟ یا اگر نکته خاصی هست بنده خیلی دوست دارم بشونم.
    با تشکر

  2. #2

    نقل قول: اختلاف بین تایمر ها در دلفی

    سلام.
    خطای درحد یک ثانیه معموله، و این موضوع برمی گرده به این که میلی ثانیه شما دقیقا الان چنده، مثلا ممکنه 999 باشه و نتیجه نهایی با اختلاف یک میلی ثانیه یک ثانیه گرفته خواهد شد.

    از طرفی تایمر وقتی باهاش رو تعداد بالا کار می کنید خطاش رو نشون می ده، حالا چطور، ببینید:
    شما فرض کن تایمری داری که قراره هر یک ثانبه چیزی رو چک کنه، تایمر براساس اصول ترد (thread) در ویندوز، بنا شده و suspend و resume می شه، ویندوز هم بنا به صلاحدید خودش ممکنه دقیقا در لحظه ای که مد نظر شماست، ترد رو ساسپند نکنه و یکم اختلاف داشته باشه، مثلا ترد با اولویت بالاتر در صف داشته باشه. حالا اگر این اختلاف برای هر دور ساسپند شدن، دو هزارم ثانیه باشه، در هزار دور می شه دو ثانیه.
    اما راه درست، اینه که به جای شمارش تعداد و ضرب اون در interval ، و در نتیجه خطا ضرب در تعداد شمارش، بیایید هر بار نتیجه نهایی رو مقایسه کنید با زمانی که قرار بوده باشه، مثل این:


    procedure TForm1.FormCreate(Sender: TObject);
    begin
    {old fasion
    Caption := TimeToStr(Time);
    Timer1.Tag := 0;
    Timer1.Interval := 1000;
    Timer1.Enabled := true;
    }


    Timer1.Tag := GetTickCount {or high resolution APIs} + 1000 {interval} * 100 {period};
    Timer1.Interval := 100;
    Timer1.Enabled := true;
    end;


    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
    {old fasion
    Timer1.Tag := Timer1.Tag +1;


    if Timer1.Tag = 100 then
    ShowMessage(TimeToStr(Time));
    }


    if Timer1.Tag <= GetTickCount {or high resolution APIs} then
    ShowMessage('Horaaaaaa');
    end;




    اما این که کلا تایمری ران نشه، باید با دقت بیشتری بررسی بشه، شاید ران می شه ولی نه دقیقا سر تایم!
    آخرین ویرایش به وسیله یوسف زالی : دوشنبه 15 دی 1393 در 08:16 صبح
    توابع تبدیل تاریخ با دقت 5000 سال
    پذیرش پروژه، کامپوننت، آموزش برنامه نویسی (دلفی، اس کیو ال، ..) -> 09123780840
    پایگاه داده، تیونینگ، طراحی و پیاده سازی ..

  3. #3

    نقل قول: اختلاف بین تایمر ها در دلفی

    تایمر براساس اصول ترد (thread) در ویندوز، بنا شده و suspend و resume می شه، ویندوز هم بنا به صلاحدید خودش ممکنه دقیقا در لحظه ای که مد نظر شماست، ترد رو ساسپند نکنه و یکم اختلاف داشته باشه، مثلا ترد با اولویت بالاتر در صف داشته باشه
    تایمر بر اساس اصول ترد بنا نشده :)
    تایمرها چند نوع مختلف در ویندوز دارن که نوع معمول که در اکثر زبان های برنامه نویسی منجمله Delphi استفاده میشه نوع message base ش هست ؛ این نوع تایمر ها با تابع SetTimer خودشون رو در ویندوز رجیستر میکنن و ویندوز وظیفه داره در زمان تائین شده برای Interval که در تابع SetTimer پاس داده شده به هندل پنجره ی پاس داده شده در همین تابع پبغام WM_Timer رو ارسال کنه :

    procedure TTimer.UpdateTimer;
    begin
    KillTimer(FWindowHandle, 1);
    if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
    if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
    raise EOutOfResources.Create(SNoTimers);
    end;


    وظیفه پنجره یاد شده این هست که پیغام WM_Timer رو هندل کنه و وقتی دریافتش کرد عملیات مناسب باهاش رو انجام بده :

    procedure TTimer.WndProc(var Msg: TMessage);
    begin
    with Msg do
    if Msg = WM_TIMER then
    try
    Timer;
    except
    Application.HandleException(Self);
    end
    else
    Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
    end;


    در دلفی پیاده سازی تایمر به این صورت هست که یه پنجره مخفی در زمان ساخته شدن ترد ایجاد میشه و هندل این پنجره به تابع SetTimer ارسال میشه تا پیغام های Tick این تایمر از طرف ویندوز به این هندل ارسال بشه ( خط آخر ) :
    constructor TTimer.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    FEnabled := True;
    FInterval := 1000;
    FWindowHandle := AllocateHWnd(WndProc);
    end;


    در ویندوز در هر ثانیه هزاران پیغام بین ویندوز و پنجره ها تبادل میشه و پیغام های زیادی هم وجود دارن که Broadcast میشن یعنی مقصد مشخصی ندارن و به همه ی پنجره های دارای هندل Valid ارسال میشن ، خوب پس Message Handler با تعداد پیغام های بسیار زیادی رو به رو هست که در صف پردازشیش ( Message Queue ) قرار دارند و باید همرو پردازش کنه و در صورت نیاز بهشون پاسخ بده ، در همین پیاده سازی تایمر دلفی در کد مربوط به override کردن تابع WndProc که در بالا قرار دادم اگر به خط آخر دقت کنید میبینید که وقتی پیغامی رسید و نوعش WM_Timer نبود دلفی تابع DefWindowProc رو صدا میزنه (API) که وظیفش صدا زدن default handler مربوطه هست تا پیغام به صورت پیش فرض پردازش بشه .

    یکی از عوامل کندی تایمر دلفی به همین دلیل هست ؛ و اینکه میگید تایمرها بر اساس ترد در ویندوز پیاده سازی شدن و suspend و resume میشن درست نیست .
    دیگر عامل کندی این تایمر ها این هست که به صورت User mode پیاده سازی شدن و ویندوز تضمینی بابت ارسال پیغام WM_Timer سر زمان تعیین شده نمیده و ممکنه چند میلی ثانیه اختلاف وجود داشته باشه .

    اگر زمان بندی خیلی دقیقی در سناریوتون مورده نیازه باید از High Resolution Timer ها استفاده کنید ، مثل : waitable تایمرها و queue تایمرها و multimedia تایمرها

    این مقاله هم نحوه استفادشون رو کامل توضیح داده : http://www.codeproject.com/Articles/...imers-Tutorial

    موفق باشید .

  4. #4

    نقل قول: اختلاف بین تایمر ها در دلفی

    به به بسیار خوش آمدید دوست عزیز!
    اینکه میگید تایمرها بر اساس ترد در ویندوز پیاده سازی شدن و suspend و resume میشن درست نیست .
    ممنون از اصلاحیه. یادمه قبل تر ها تو SO دیده بودم، پس نیازه که مجدد مطالبش رو ببینم.
    در کل این طور استفاده کردن از تایمر درست نیست، که بیاییم و زمان های کوتاه رو در تعداد بالا بشمریم.
    در ترد ها هم همین مطلب هست، یعنی نمی شه توقع داشت که دقیقا سر زمانی که ما بهش گفتیم، اون هم در تعدادهای بالا، زمان بندی ما درست از آب بیرون بیاد.
    بیشتر باش فلونی جان.
    توابع تبدیل تاریخ با دقت 5000 سال
    پذیرش پروژه، کامپوننت، آموزش برنامه نویسی (دلفی، اس کیو ال، ..) -> 09123780840
    پایگاه داده، تیونینگ، طراحی و پیاده سازی ..

  5. #5

    نقل قول: اختلاف بین تایمر ها در دلفی

    با سلام،
    یادمه قبل تر ها تو SO دیده بودم، پس نیازه که مجدد مطالبش رو ببینم.
    من هم قبلاً مطلبی رو در این خصوص خونده بودم و تا جایی که یادمه جایی میگفت که priority تایمر پیش فرض دلفی از نوع Idle هست! ولی الان بعد از رسیدن به این مطلب فهمیدم که قضیه فرق میکنه :
    http://stackoverflow.com/questions/1...mer-not-firing

    خطاب به sajoo :
    برای راحتی کار میشه به جای تایمر پیش فرض از تایمرهای دیگری نظیر TJvTimer از مجموعه JVCL استفاده کرد که خاصیتی به نام ThreadPriority داره که میشه مقادیر مختلفی مثل tpIdle و tpNormal و tpHighest و ... رو به اون اختصاص داد. البته باید خاصیت Threaded اون رو هم به True ست کنید.
    آخرین ویرایش به وسیله BORHAN TEC : شنبه 20 دی 1393 در 23:56 عصر

  6. #6
    کاربر دائمی آواتار Delphi Coder
    تاریخ عضویت
    آذر 1386
    محل زندگی
    c:\windows\system32
    پست
    579

    نقل قول: اختلاف بین تایمر ها در دلفی

    مولتی مدیا تایمر به مراتب خیلی دقیقتر هست و به احتمال زیاد کارتونو راه میندازه. البته من دقیق نبودن مولتی مدیا تایمر رو تجربه کردم (حدود 15 الی 30 ثانیه اختلاف در 2 ساعت تجربه ای هست که من طی چندین تست داشتم) ولی فکر میکنم اختلافش برای کارهای این تیپی قابل اغماض هست. اگر دنبال دقت بیشتری هستید Waitable و Queue Timers رو امتحان کنید من خودم تست نکردم اگر شما اینکار رو کردید لطف کنید و نتیجه رو به ما هم اطلاع بدید.

  7. #7
    کاربر دائمی آواتار hamedjim
    تاریخ عضویت
    مهر 1393
    محل زندگی
    تهران
    پست
    140

    نقل قول: اختلاف بین تایمر ها در دلفی

    دوستان سلام.
    من هم برای ارسال یک سری دیتا از طریق پورت سریال نیاز دارم تا دقیقا هر 100 میلی ثانیه یک سری کد رو ارسال کنم. به روشی که دوستان توضیح دادند از GetTickCount به این شکل استفاده کردم:
    در هنگام ایجاد فرم، مقدار GetTickCount رو دریافت می‌کنیم:


    LastTicks := GetTickCount;
    LabelTick.Caption:='';
    LabelTime.Caption:='';
    Timer1.Enabled:=False;
    Timer1.Interval:=5;



    Interval رو هم برای تایمر مقداری کمتر از حد مورد نیاز قرار دادم تا روتین مربوط به وقفه تایمر سریعتر چک بشه. کد زیربرنامه تایمر رو هم به این شکل نوشتم:


    procedure TForm1.Timer1Timer(Sender: TObject);
    var
    CurTicks, Elapsed: DWORD;
    begin
    CurTicks :=GetTickCount; {هر 49.7 روز صفر می شود}

    if CurTicks >= LastTicks then
    Elapsed := CurTicks - LastTicks
    else
    Elapsed := ($FFFFFFFF - LastTicks) + CurTicks;


    if Elapsed >= Interval then
    begin
    LastTicks := CurTicks;
    LabelTick.Caption:=FormatInClock(CurTicks);
    LabelTime.Caption:=TimeToStr(Time);

    {.
    .
    .
    کدهای برنامه
    .
    .
    .}

    end;
    end;


    توضیح اینکه وقتی Elapsed به اندازه Interval برسه می تونیم کدهایی که برای وقفه نیاز داریم رو قرار بدیم. Interval مقدار ثابت (Const) مورد نظرمون برای وقفه هست.

    میشه نظرتون رو در این مورد اعلام کنید؟
    نمونه برنامه نوشته شده با XE2 رو هم به طور کامل ضمیمه میکنم:


    Accurate Timer.rar
    آخرین ویرایش به وسیله hamedjim : سه شنبه 07 بهمن 1393 در 13:50 عصر

  8. #8

    نقل قول: اختلاف بین تایمر ها در دلفی

    دلیل وجود این کدها چیه؟

    if CurTicks >= LastTicks then
    Elapsed := CurTicks - LastTicks
    else
    Elapsed := ($FFFFFFFF - LastTicks) + CurTicks;


    توابع تبدیل تاریخ با دقت 5000 سال
    پذیرش پروژه، کامپوننت، آموزش برنامه نویسی (دلفی، اس کیو ال، ..) -> 09123780840
    پایگاه داده، تیونینگ، طراحی و پیاده سازی ..

  9. #9
    کاربر دائمی آواتار hamedjim
    تاریخ عضویت
    مهر 1393
    محل زندگی
    تهران
    پست
    140

    نقل قول: اختلاف بین تایمر ها در دلفی

    تا اونجا که من فهمیدم توسط تابع GetTickCount زمان سیستم رو میشه دریافت کرد. این زمان هر 49.7 روز صفر میشه.
    زمان دوبار، یکی زمان ایجاد فرم و یکی در وقفه تایمر گرفته میشه و اختلافش میشه مدت زمانی که از زمان ایجاد فرم تا زمان ورود به وقفه تایمر اتفاق افتاده. و میشه توسط یه تابع ساده مقدارش رو بر حسب روز و ساعت و دقیقه و ثانیه و میلی ثانیه بدست آورد. قسمت else هم برای زمانی هست که نمونه‌گیری زمانی اول قبل از صفر شدن GetTickCount و نمونه‌گیری دوم بعد از صفر شدنش اتفاق بیفته.


    اما بعد از امتحان کردن این روش، به این نتیجه رسیدم که خیلی سطحی به این برنامه نگاه کردم. این روش مناسبی برای بدست آوردن یک زمان دقیق نیست.
    شما لطف می کنید و بگید من چطور می تونم دقیقا هر x میلی ثانیه به روتین وقفه برم و عملیاتی رو انجام بدم؟

  10. #10
    کاربر دائمی آواتار hamedjim
    تاریخ عضویت
    مهر 1393
    محل زندگی
    تهران
    پست
    140

    نقل قول: اختلاف بین تایمر ها در دلفی

    خب فکر می‌کنم به یه نتایجی رسیدم.
    این‌بار با استفاده از MultiMedia Timer یه برنامه نوشتم که نتایج قابل قبولی رو بهم داد.
    وقتی تابع timeSetEvent اجرا میشه، MultiMedia Timer اجرا میشه و با توجه به مقادیر آرگومان‌های تابع، به TimeCallBack میره.


    uses
    ;MMSystem

    ...

    فرمان اجرای تایمر:
    mmResult := TimeSetEvent(10, 0, @TimeCallBack, 0, TIME_PERIODIC);

    ...

    دستورات مورد نظر در زیربرنامه TimeCallBack نوشته می شود.
    procedure TimeCallBack(TimerID, Msg: Uint; dwUser, dw1, dw2: DWORD); pascal;




    نمونه برنامه:

    MutliMedia Timer.rar


    نتیجه برنامه بعد از 83 دقیقه و 21 ثانیه:
    Result.jpg
    آخرین ویرایش به وسیله hamedjim : چهارشنبه 08 بهمن 1393 در 21:52 عصر

  11. #11

    نقل قول: اختلاف بین تایمر ها در دلفی

    سلام
    تابع TimeGetTime در دلفی 2010 برای کپی کردن و نمایش زمان کپی اشکال میگیره لطفا راهنمایی کنید

  12. #12

    نقل قول: اختلاف بین تایمر ها در دلفی

    سلام. چه اروری؟ کدتون چیه؟ الان چطور باید ما بفهمیم چی نوشتید و چی ارور گرفتید؟
    توابع تبدیل تاریخ با دقت 5000 سال
    پذیرش پروژه، کامپوننت، آموزش برنامه نویسی (دلفی، اس کیو ال، ..) -> 09123780840
    پایگاه داده، تیونینگ، طراحی و پیاده سازی ..

  13. #13

    نقل قول: اختلاف بین تایمر ها در دلفی

    سلام در قسمت نمایش زمان در ProgressBar هنگام کامپایل کردن از تابع TimeGetTime ارور نامشخص بودن تابع را میدهد. این تابع TimeGetTime را چطور باید معرفی کنم

  14. #14

    نقل قول: اختلاف بین تایمر ها در دلفی

    تابع نمایش زمان به هنگام کپی را از همین سایت گرفتم. اگر مفهوم را نرساندم ارور را برای شما ارسال میکنم

  15. #15

    نقل قول: اختلاف بین تایمر ها در دلفی

    uses DateUtils رو امتحان کنید
    آخرین ویرایش به وسیله یوسف زالی : سه شنبه 09 بهمن 1403 در 00:57 صبح
    توابع تبدیل تاریخ با دقت 5000 سال
    پذیرش پروژه، کامپوننت، آموزش برنامه نویسی (دلفی، اس کیو ال، ..) -> 09123780840
    پایگاه داده، تیونینگ، طراحی و پیاده سازی ..

  16. #16

    نقل قول: اختلاف بین تایمر ها در دلفی

    سلام خیلی سپاسگزارم انجام شد ارور برنامه برطرف شد.

  17. #17

    نقل قول: اختلاف بین تایمر ها در دلفی

    نقل قول نوشته شده توسط sajioo مشاهده تاپیک
    سلام دوستان گلم
    سوالم را اینطور مطرح می کنم
    بنده بر روی فرمم برای مثال 10 تایمر دارم که هر تایمر یک کار خاصی انجام میده.
    وظیفه ی تایمر 1 اینه که از 1 تا 1000 با فاصله ی زمانی 1 ثانیه شمارش انجام بده و وقتی به 1000 رسید به کاربر پیام بده که 1000 ثانیه است که در برنامه فعال است.
    طی یک سری بررسی ها که داشتم دیدم این تایم متفاوت هستش.
    برای مثال وقتی طی این 1000 ثانیه من با برنامه فعال هستم و در حال کار کردن اگر قرار باشه با توجه به ساعت ویندوز برنامه من ساعت 10:20:20 به من پیام بده بعضی وقتا 10:20:30 یا حتی بعضی وقتا 10:20:55 ثانیه به من پیام داده .این عقب افتادگی زمانی برای چیه ؟ آیا دلیل خاصی داره؟

    سوال دوم بنده هم در خصوص تایمر هست باز
    برای مثال من فرم 4 برنامه خود را گفتم هروقت show شد تایمر 2 فعال بشه و بعد از 10 ثانیه فرم 4 رو hide کنه. این تایمر اکثر مواقع درست کار میکنه اما جدا بعضی وقتا عمل نمیکنه .
    حالا دقیقا نمیدونم چرا ؟ ولی خودم تست کردم و مطمئن شدم مثلا از 100 بار 1 بار این عمل نمیکنه. واقعا دلیل این موضوع چیه ؟ یا اگر نکته خاصی هست بنده خیلی دوست دارم بشونم.
    با تشکر
    اینم یه تست بزن:


    var
    Form1: TForm1;
    StartTime, EndTime, NowTime: TDateTime;


    implementation


    {$R *.dfm}


    uses System.DateUtils;


    procedure TForm1.FormCreate(Sender: TObject);
    begin
    StartTime := Now;
    EndTime := IncSecond(StartTime, 1000);
    Timer1.Interval := 1000;
    Timer1.Enabled := True;
    end;


    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
    NowTime := Now;
    if NowTime >= EndTime then
    begin
    Timer1.Enabled := False;
    ShowMessage('1000 seconds have passed in the program.');
    end;
    end;
    آخرین ویرایش به وسیله دلفــي : دوشنبه 15 بهمن 1403 در 13:14 عصر

تاپیک های مشابه

  1. تابع اختلاف بین دو ساعت(فوری)
    نوشته شده توسط iranigirl1364 در بخش C#‎‎
    پاسخ: 4
    آخرین پست: دوشنبه 12 اردیبهشت 1390, 16:53 عصر
  2. بدست آوردن اختلاف بین دو تاریخ
    نوشته شده توسط babak23 در بخش C#‎‎
    پاسخ: 1
    آخرین پست: یک شنبه 04 آذر 1386, 19:58 عصر
  3. پیدا کردن اختلاف بین دو زمان
    نوشته شده توسط na3er-faraji در بخش برنامه نویسی در 6 VB
    پاسخ: 11
    آخرین پست: دوشنبه 10 اردیبهشت 1386, 14:47 عصر
  4. اختلاف بین دو زمان به صورت دقیقه
    نوشته شده توسط راحله سعادتی در بخش برنامه نویسی در Delphi
    پاسخ: 6
    آخرین پست: چهارشنبه 24 اسفند 1384, 12:31 عصر
  5. اختلاف بین دو زمان
    نوشته شده توسط فاطمه هاشمیان در بخش C#‎‎
    پاسخ: 2
    آخرین پست: سه شنبه 24 خرداد 1384, 19:18 عصر

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •