You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
Well, Ok, not really all that self-evident... but it does mean that DDT must be doing something to implement CONTROL GET TEXT which results in a WM_GETTEXT message or something else which must execute in the context of the thread in which the window (dialog) was created... but whatever that is cannot get done because that thead is currently suspended on a WFSO.
Meaning... CONTROL GET TEXT cannot be used when the thread in which the dialog was created is in a wait state.
Like I said... this is not documented where it should be, under the CONTROL GET TEXT statement.
AFAIK - and I am NOT a 'DDT' guy - there are no restrictions vis-a-vis 'DDT in Multithreaded applications' than there are in general on 'DDT in any application' or on 'multi-threaded applications using the PB compilers.'
I was thinking about your comment in the source code of the last example quoyted, where you say
' I had to use a string ptr here instead of CONTROL GET TEXT because the calling thread was in a wait
' state (WaitForSingleObject) and apparently (undocumented but not reasonably) CONTROL GET TEXT does
' "something" which must execute in the context of the same thread (suspended) as the dialog.
' Apparently (that means also not documented), DIALOG GET USER does not need to execute anything in the
' context of the thread in which the dialog was created.
I don't like GLOBALs because it makes code less re-useable; and more difficult to port to a separate module (DLL) within the same application. I also tend to forget the names of GLOBAL variables, but that's probably not a real good excuse.
DIALOG DOEVENTS is not ugly; looping on a variable's value is ugly: it's inefficient. But since you brought it up, I also consider it ugly to use additional "inline" message loops at multiple points within a program.
AFAIK - and I am NOT a 'DDT' guy - there are no restrictions vis-a-vis 'DDT in Multithreaded applications' than there are in general on 'DDT in any application' or on 'multi-threaded applications using the PB compilers.'
Same application stopping a long running process in a seperate thread.
Just to show how simple your threads can be in an extreme case!
Code:
#COMPILE EXE
#DIM ALL
#INCLUDE "WIN32API.INC"
#INCLUDE "COMMCTRL.INC"
%IDD_DIALOG1 = 101
%IDC_BUTTON1 = 1001
%IDC_BUTTON2 = 1002 '
%IDC_PROG1 = 1006
GLOBAL gflag AS LONG
'-------------------------------------------------------------------------------
SUB long_runner ( hD AS DWORD, t AS DOUBLE)
LOCAL n, untilnow, tstart AS DOUBLE
tstart = TIMER
WHILE untilnow < t
CONTROL SEND hD, %IDC_PROG1, %PBM_SETPOS, untilnow*100/t, 0
IF gflag = 1 THEN
? "interrupted!"
EXIT SUB
END IF
INCR n
untilnow = TIMER - tstart
SLEEP 50
WEND
? "finished long runner"
END SUB
'-------------------------------------------------------------------------------
FUNCTION wThread ( BYVAL hD AS DWORD) AS LONG
long_runner ( hD, 20)
END FUNCTION
'-------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()
LOCAL lresult, n AS LONG
STATIC hwthread AS LONG
SELECT CASE AS LONG CBMSG
CASE %WM_INITDIALOG
CASE %WM_COMMAND
SELECT CASE AS LONG CBCTL
CASE %IDC_BUTTON1
IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
THREAD CREATE wthread(CBHNDL) TO hwthread
THREAD CLOSE hwThread TO lresult
gflag = 0
END IF
CASE %IDC_BUTTON2
gflag = 1
END SELECT
CASE %WM_DESTROY
END SELECT
END FUNCTION
'-----------------------------------------------------------------------
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
LOCAL lRslt AS LONG
LOCAL hDlg AS DWORD
DIALOG NEW hParent, "Interrupt a long-running process", 175, 118, 170, 58, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
%WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
%WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Start", 5, 35, 30, 15
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON2, "Stop", 55, 35, 30, 15
CONTROL ADD "msctls_progress32", hDlg, %IDC_PROG1, "msctls_progress32_1", 5, 10, 140, 15, %WS_CHILD OR _
%WS_VISIBLE
DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
FUNCTION = lRslt
END FUNCTION
'============================================================================
FUNCTION PBMAIN()
InitCommonControls
ShowDIALOG1 %HWND_DESKTOP
END FUNCTION
Using Dialog DoEvents to allow message processing so that a control can be used to interrupt a long running process:
Code:
#COMPILE EXE
#DIM ALL
#INCLUDE "WIN32API.INC"
#INCLUDE "COMMCTRL.INC"
%IDD_DIALOG1 = 101
%IDC_BUTTON1 = 1001
%IDC_BUTTON2 = 1002 '*
%IDC_TEXTBOX1 = 1003 '*
%IDC_RESULTS_LB = 1004 '*
%IDC_STATS_LAB = 1005 '*
%IDC_PROG1 = 1006
GLOBAL gflag AS LONG
'-------------------------------------------------------------------------------
SUB long_runner ( hD AS DWORD, t AS DOUBLE)
LOCAL i, j, k AS LONG
LOCAL n, untilnow, tstart AS DOUBLE
tstart = TIMER
WHILE untilnow < t
CONTROL SEND hD, %IDC_PROG1, %PBM_SETPOS, untilnow*100/t, 0
IF gflag = 1 THEN
? "interrupted!"
EXIT SUB
END IF
INCR n
untilnow = TIMER - tstart
DIALOG DOEVENTS 1
SLEEP 50
WEND
? "finished long runner"
END SUB
'-------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()
LOCAL lresult, n AS LONG
SELECT CASE AS LONG CBMSG
CASE %WM_INITDIALOG
CASE %WM_COMMAND
SELECT CASE AS LONG CBCTL
CASE %IDC_BUTTON1
IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
long_runner(CBHNDL, 20)
gflag = 0
END IF
CASE %IDC_BUTTON2
gflag = 1
END SELECT
CASE %WM_DESTROY
END SELECT
END FUNCTION
'-----------------------------------------------------------------------
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
LOCAL lRslt AS LONG
LOCAL hDlg AS DWORD
DIALOG NEW hParent, "Interrupt a long-running process", 175, 118, 170, 58, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
%WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
%WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Start", 5, 35, 30, 15
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON2, "Stop", 55, 35, 30, 15
CONTROL ADD "msctls_progress32", hDlg, %IDC_PROG1, "msctls_progress32_1", 5, 10, 140, 15, %WS_CHILD OR _
%WS_VISIBLE
DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
FUNCTION = lRslt
END FUNCTION
'============================================================================
FUNCTION PBMAIN()
InitCommonControls
ShowDIALOG1 %HWND_DESKTOP
END FUNCTION
Last edited by Chris Holbrook; 27 May 2008, 10:22 AM.
Reason: removed spurious statemenst
MCM, thanks for your reply, it lead me indirectly to this thread and Chris Boss's suggestion, which so far works 100% in my test context, no need for threads at all, just put a DIALOG DOEVENTS in the slow running part.
Unfortunately, it would not work if the slow running bit was an external call - as mine is in the "real world" so it's back to threads again!
I have very little experience of threads, just what I've read in the help and read here. I don't have any conceptual problems with concurrent stuff, just never dabbled with it in Windows or PB.
The application runs a long running process which can be interrupted by setting a flag. In my first attempt, the thread which sets the flag puts up a MSGBOX, sets the flag and clears the msgbox when the MSGBOX button is clicked. This works, but if the button is NOT clicked, how to get rid of the MSGBOX? CLOSE THREAD doesn't do it.
Is there a way in which the new thread can get messages from a button in the dialog created by the main process, rather than starting a new (MSGBOX) window? This would look better.
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Leave a comment: