امتیاز موضوع:
  • 0 رأی - میانگین امتیازات: 0
  • 1
  • 2
  • 3
  • 4
  • 5
DoEvents چیست و چگونه عمل می کند...
نویسنده پیام
1120 آفلاین
در حال پیشرفت
***

ارسال‌ها: 313
موضوع‌ها: 49
تاریخ عضویت: دى ۱۳۸۷

تشکرها : 404
( 381 تشکر در 161 ارسال )
ارسال: #1
DoEvents چیست و چگونه عمل می کند...
سلام .

بار ها در تاپیک های مختلف دیدم که راجع به دستور DoEvents ( در دلفی Application.ProcessMessages ، در سی شارپ Application.DoEvents ) بحث شده ، این تابع مخصوصا در vb6 که از برنامه نویسی چند نخی پشتیبانی نمی کند بسیار پر کاربرد هست و همانطور که می دانید در حلقه های طولانی به منظور جلوگیری از به اصطلاح هنگ کردن برنامه استفاده می شود .
اما واقعا این دستور چه کاری انجام می دهد و چگونه پیاده سازی شده است ؟

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

کد:
For i = 0 To 10000
  Me.Caption = CStr(i)
Next i

کد:
for (int i = 0; i <= 10000; i++)
{
    this.Text = i.ToString();
    Application.DoEvents();
}

کد:
for i := 0 to 10000 do
begin
  self.Caption := IntToStr(i);
  Application.ProcessMessages;
end;

اما کاری که DoEvents انجام می دهد : به زبان ساده این دستور باعت می شود که پیام های موجود در صف پیام ویندوز پردازش شوند و نسبت به آنها واکنش نشان داده شود (مانند بروز رسانی های گرافیکی و...) و مجددا کنترل به برنامه باز گشته و اجرای دستورات ادامه یابد .

اما این روند چگونه پیاده سازی شده است ؟

با استفاده از توابع:
PeekMessage برای چک کردن صف پیام و بازیافت پیام در صورت وجود .
TranslateMessage برای ترجمه پیام .
DispatchMessag برای مخابره کردن پیام .

نحوه پیاده سازی دستور DoEvents در VB6 :

کد:
' Arshamsoft
' www.arshamsoft.com

Option Explicit

Private Type POINTAPI
        x As Long
        y As Long
End Type

Private Type Msg
    hwnd As Long
    message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type


Private  Declare Function PeekMessageA Lib "user32" (lpMsg As Msg, ByVal hwnd As  Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal  wRemoveMsg As Long) As Long
Private Declare Function PeekMessageW Lib  "user32" (lpMsg As Msg, ByVal hwnd As Long, ByVal wMsgFilterMin As  Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long

Private Declare Function TranslateMessage Lib "user32" (lpMsg As Msg) As Long

Private Declare Function DispatchMessageA Lib "user32" (lpMsg As Msg) As Long
Private Declare Function DispatchMessageW Lib "user32" (lpMsg As Msg) As Long

Private Declare Function IsWindowUnicode Lib "user32" (ByVal hwnd As Long) As Long


Private Const PM_REMOVE = &H1



Public Sub DoEventsX()
    Dim cMsg As Msg
    Dim Unicode As Boolean
    
    Unicode = (cMsg.hwnd = 0) Or IsWindowUnicode(cMsg.hwnd)
    
    Do
        If Unicode = True Then
           If PeekMessageW(cMsg, 0, 0, 0, PM_REMOVE) = 0 Then Exit Do
        Else
           If PeekMessageA(cMsg, 0, 0, 0, PM_REMOVE) = 0 Then Exit Do
        End If
        
        TranslateMessage cMsg
        
        If Unicode = True Then
           DispatchMessageW cMsg
        Else
           DispatchMessageA cMsg
        End If
    Loop
    
End Sub


Private Sub Command1_Click()
  Dim i As Integer
  
  For i = 0 To 10000
    Me.Caption = CStr(i)
    DoEventsX
  Next i
End Sub

امیدوارم این مطلب برای دوستان مفید واقع بشه .

موفق و آزاد باشید Wink.

این روند در دلفی با جزییات بیشتر و به صورت زیر در یونیت Vcl.Forms پیاده سازی شده :

کد:
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=True)]

function TApplication.ProcessMessage(var Msg: TMsg): Boolean;

var

  Handled: Boolean;

  Unicode: Boolean;

  MsgExists: Boolean;

begin

  Result := False;

  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then

  begin

    Unicode := (Msg.hwnd = 0) or IsWindowUnicode(Msg.hwnd);

    if Unicode then

      MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)

    else

      MsgExists := PeekMessageA(Msg, 0, 0, 0, PM_REMOVE);



    if MsgExists then

    begin

      Result := True;

      if Msg.Message <> WM_QUIT then

      begin

        Handled := False;

        if Assigned(FOnMessage) then FOnMessage(Msg, Handled);

        if not IsPreProcessMessage(Msg) and not IsHintMsg(Msg) and

          not Handled and not IsMDIMsg(Msg) and

          not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then

        begin

          TranslateMessage(Msg);

          if Unicode then

            DispatchMessageW(Msg)

          else

            DispatchMessageA(Msg);

        end;

      end

      else

      begin

  {$IF DEFINED(CLR)}

        if Assigned(FOnShutDown) then FOnShutDown(self);

        DoneApplication;

  {$IFEND}

        FTerminate := True;

      end;

    end;

  end;

end;



[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]

procedure TApplication.ProcessMessages;

var

  Msg: TMsg;

begin

  while ProcessMessage(Msg) do {loop};

end;

(آخرین ویرایش در این ارسال: ۲۵-دى-۱۳۹۱, ۲۰:۳۶:۰۱، توسط 1120.)
۲۵-دى-۱۳۹۱, ۲۰:۰۷:۵۹
ارسال‌ها
پاسخ
تشکر شده توسط : Di Di, Payman62


موضوعات مرتبط با این موضوع...
موضوع نویسنده پاسخ بازدید آخرین ارسال
Wink res چیست چکار میکند و چگونه یک res بسازیم HoseinVig 13 20,460 ۰۶-تير-۱۳۹۵, ۱۷:۵۰:۲۹
آخرین ارسال: Ghoghnus
  [سوال] فرق کد نوشتن در Class و Modul چیست؟ eppagh 3 3,189 ۰۹-مرداد-۱۳۹۳, ۰۹:۵۴:۵۷
آخرین ارسال: babyy
  تفاوت ocx و dll در چیست؟ mehrdad8 1 3,979 ۲۸-خرداد-۱۳۹۲, ۱۱:۳۱:۴۸
آخرین ارسال: Payman62
  stream چیست؟ mehrdad8 3 3,377 ۱۳-خرداد-۱۳۹۲, ۱۷:۱۳:۱۶
آخرین ارسال: babyy
  چگونه يه فايل ocx را به برنامه خود بچسبانيم rap0661 16 12,812 ۱۹-شهریور-۱۳۹۱, ۱۸:۲۴:۵۱
آخرین ارسال: rap0661
  چگونه يه تايمر را روي فرم قرار دهيم و مدت اجرا آن را به يك ساعت تغيير دهيم! rap0661 10 11,357 ۱۱-خرداد-۱۳۹۱, ۱۹:۵۶:۵۸
آخرین ارسال: Ghoghnus
  [سوال] چگونه میتونم صدای ویندوز میدیا پلیر رو ضبط کنم؟ mahmoodhojabri 7 8,819 ۰۱-اسفند-۱۳۹۰, ۰۲:۲۴:۰۹
آخرین ارسال: abbasalifix
  سوال چگونه فايل خود را تكثير كنيم rap0661 2 3,332 ۲۵-بهمن-۱۳۹۰, ۱۹:۰۵:۲۱
آخرین ارسال: rap0661
  چگونه میتوان اطلاعات مربوط به یک پروسه رم را خواند؟ sylvester 10 8,870 ۱۶-بهمن-۱۳۸۸, ۲۱:۵۱:۲۵
آخرین ارسال: sylvester
  چگونه textBox مثل office 2007 داشته باشيم skh1300 3 3,623 ۱۱-دى-۱۳۸۸, ۰۰:۳۳:۰۳
آخرین ارسال: skh1300

پرش به انجمن:


کاربرانِ درحال بازدید از این موضوع: 1 مهمان

صفحه‌ی تماس | IranVig | بازگشت به بالا | | بایگانی | پیوند سایتی RSS