It is simple, but clearly demonstrates the far better responsiveness that multitasking provides.
To use the program, click the button labelled "Run Nonthreaded" and then [try to] quickly click the "Test Responsiveness" button a few times. The result is very unsatisfactory.
But now repeat the test with the "Run Multithreaded" and "Test Responsiveness" buttons and you will see a dramatic difference even though the underlying code is almost identical.
The combination of "Run Multithreaded" and "Exit" buttons is also very responsive.
Code: Select all
; Multithreaded Response
; www.codeguru.com/columns/dotnet/article.php/c4593
; When either the "Run Nonthreaded" or "Run Multithreaded" buttons are pressed
; they will be temporarily disabled and a list box will be filled with
; "Hello World" messages with a delay between each.
; The window also contains a button to test the interface responsiveness while
; the list box is being populated.
; The click events of the "Run Nonthreaded" and "Run Multithreaded" buttons
; result in the same procedure being executed. The only difference is that when
; the "Run Multithreaded" button is pressed the method is executed in a new thread.
#Program$ = "Multithreaded Response"
#Version$ = "1.0"
EnableExplicit
; Constants
Enumeration
#winMain
#lblResponse
#txtResponse
#lstHello
#butNonthread
#butThreaded
#butTest
#butExit
EndEnumeration
Declare FillList(*value)
Declare ToggleButtons(toggle)
; GUI Metrics
Define gap, lstw, lsth, butw, buth, winw, winh
Define lblw, lblh, txtw, txth
gap = 20
lblw = 100: lblh = 24
txtw = 100: txth = lblh
lstw = 500: lsth = 200
butw = 150: buth = 30
winw = lstw+gap*2: winh = txth+lsth+buth*2+gap*7
; Create GUI
Define title$, flags, x, y
title$ = " "+#Program$+" "+#Version$
flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered
OpenWindow(#winMain, 0, 0, winw, winh, title$, flags)
; Labelled text box
y = gap: x = gap
TextGadget(#lblResponse, x, y+4, lblw, lblh, "Click Response")
x + lblw
StringGadget(#txtResponse, x, y, txtw, txth, "")
; List gadget
y + txth+ gap*2: x = gap
ListViewGadget(#lstHello, x, y, lstw, lsth)
; Buttons
y + lsth+gap*2: x = gap
ButtonGadget(#butNonthread, x, y, butw, buth, "Run Nonthreaded")
x = (winw-butw)/2
ButtonGadget(#butThreaded, x, y, butw, buth, "Run Multithreaded")
y + buth+gap: x = butw/2+gap*3/2
ButtonGadget(#butTest, x, y, butw, buth, "Test Responsiveness")
x = winw-butw-gap
ButtonGadget(#butExit, x, y, butw, buth, "E x i t")
; Event loop
Define done=#False
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget, #PB_Event_Menu
Select EventGadget() ; Or EventMenu()
Case #butNonthread
; Respond to the nonThreadedButton click event
FillList(1)
Case #butThreaded
; Respond to the multiThreadedButton click event
; Launch a thread to do the update
CreateThread(@FillList(), 2)
Case #butTest
; Respond to the testResponseButton click event
SetGadgetText(#txtResponse, Str(Val(GetGadgetText(#txtResponse))+1))
Case #butExit ; Exit button
done=#True
EndSelect
Case #PB_Event_CloseWindow
done=#True
EndSelect
Until done
End
Procedure FillList(*value)
Protected i
; Populate list box
Debug "Value = "+Str(*value)
ClearGadgetItems(#lstHello)
SetGadgetText(#txtResponse, "0")
ToggleButtons(#False)
For i = 0 To 9
AddGadgetItem(#lstHello, -1, "Hello World " + Str(i))
Delay(1000)
Next i
ToggleButtons(#True)
EndProcedure
Procedure ToggleButtons(toggle)
; Toggle the form buttons on or off accordingly.
DisableGadget(#butNonthread, #True-toggle)
DisableGadget(#butThreaded, #True-toggle)
EndProcedure