PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 2024 → [WD18] Referencing controls on an internal window from a different thread
[WD18] Referencing controls on an internal window from a different thread
Iniciado por rob, 03,mar. 2015 21:48 - 5 respuestas
Miembro registrado
105 mensajes
Publicado el 03,marzo 2015 - 21:48
Is there anything special I have to do to reference controls on an internal window page from a different thread?

The scenario is I have a window with an internal window control. The main window spawns a background thread that periodically checks for certain conditions.

In the event that these conditions are met, I need to modify the properties of controls on the displayed internal window. Grey out buttons, ect.

I know I can't reference the windows via IW_Name.ControlName..Property. That doesn't work.

Is there something I'm missing?

Thanks.
Publicado el 03,marzo 2015 - 23:42
Hi Rob

What you are missing is the fact that ONLY the MAIN thread can interact
with the UI... From a secondary thread, you can only use the thread
functions (there is one to call a procedure from a window, in which you
can do your stuff)

Best regards

--
Fabrice Harari
International WinDev, WebDev and WinDev mobile Consulting

NEW: WXReplication, your open source replication system is available on
my web site!!!
WXShowroom.com: Show your projects!
More information on http://www.fabriceharari.com


On 3/3/2015 3:48 PM, rob wrote:
Is there anything special I have to do to reference controls on an
internal window page from a different thread?

The scenario is I have a window with an internal window control. The
main window spawns a background thread that periodically checks for
certain conditions.

In the event that these conditions are met, I need to modify the
properties of controls on the displayed internal window. Grey out
buttons, ect.
I know I can't reference the windows via IW_Name.ControlName..Property.
That doesn't work.

Is there something I'm missing?

Thanks.
Miembro registrado
105 mensajes
Publicado el 04,marzo 2015 - 14:53
Thank you Fabrice. I'll take a look at that.

However, your statement has me a little confused. Because if that is true, then some of the code I currently have shouldn't work.

Currently, from my main window End of Init process, I'm calling the following code.
CheckConnection()
LoadDefaults()
ThreadExecute("CheckConnectionThread" ,threadNormal,CheckConnectionThreadProcedure)
IF InTestMode() = True THEN
Trace("ThreadRunning:" + threadRunning)
Trace("ThreadUnknown:" + threadUnknown)
Trace("ThreadSuspended:" + threadSuspended)
//Start timer to check connection to the server
Timer(CheckThreads,6000,999)
END


CheckCOnnectionThreadProcedure is a global procedure with the following.

Procedure CheckConnectionThreadProcedure()
LOOP
CheckConnection()
IF InTestMode() = True THEN
Trace("CheckConnectionThread: " + ThreadState("CheckConnectionThread"))
END
//Wait for ~30 seconds.
//Loop with wait is used due to the wait command locking the thread until it is completed.
//By splitting it into multiple wait commands, it's more responsive to ThreadStop calls.
FOR x = 1 TO 6
Wait(500)
END

DO WHILE True = True


Procedure CheckConnection()

xStatus is numeric
xStatus = ServerSettingsV2()
IF xStatus <> 0 THEN
ChangeLight(False)
ELSE
ChangeLight(True)
END


Procedure ChangeLight(bConnected is boolean)


SWITCH bConnected
CASE True:
WIN_Main.IMG_ServerConnectionRed..Visible = False
WIN_Main.IMG_ServerConnectionGreen..Visible = True
gbIsConnected = True
WIN_Main.STC_ConnectionStatus..Visible = True
WIN_Main.STC_ConnectionStatus..Caption = "Connected"

CASE False
WIN_Main.IMG_ServerConnectionRed..Visible = True
WIN_Main.IMG_ServerConnectionGreen..Visible = False
gbIsConnected = False
WIN_Main.STC_ConnectionStatus..Visible = True
WIN_Main.STC_ConnectionStatus..Caption = "Offline"

OTHER CASE

END

Now, I am sure this isn't the most efficient way to accomplish this. I'm still very much a beginner at programming. However, as you can see the end result of this thread is changing UI elements on the main window.

Maybe what I'm calling a thread isn't actually a secondary thread?
Publicado el 04,marzo 2015 - 15:05
Hi Rob

I did not have the time to look at your code in details, but make sure
you read all the help about the threads before you go any further with
using them...

Multithreading the UI "MAY" work in simple cases but WILL result in a
crash as soon as 2 threads try to access the same element at the same
time, which is why it is forbidden

Best regards

--
Fabrice Harari
International WinDev, WebDev and WinDev mobile Consulting

NEW: WXReplication, your open source replication system is available on
my web site!!!
WXShowroom.com: Show your projects!
More information on http://www.fabriceharari.com


On 3/4/2015 8:53 AM, rob wrote:
Thank you Fabrice. I'll take a look at that.

However, your statement has me a little confused. Because if that is
true, then some of the code I currently have shouldn't work.

Currently, from my main window End of Init process, I'm calling the
following code.
CheckConnection()
LoadDefaults()
ThreadExecute("CheckConnectionThread"
,threadNormal,CheckConnectionThreadProcedure)
IF InTestMode() = True THEN
Trace("ThreadRunning:" + threadRunning) Trace("ThreadUnknown:"
+ threadUnknown)
Trace("ThreadSuspended:" + threadSuspended)
//Start timer to check connection to the server
Timer(CheckThreads,6000,999)
END


CheckCOnnectionThreadProcedure is a global procedure with the following.

PROCEDURE CheckConnectionThreadProcedure()
LOOP
CheckConnection()
IF InTestMode() = True THEN
Trace("CheckConnectionThread: " +
ThreadState("CheckConnectionThread"))
END
//Wait for ~30 seconds.
//Loop with wait is used due to the wait command locking the thread
until it is completed.
//By splitting it into multiple wait commands, it's more responsive
to ThreadStop calls.
FOR x = 1 TO 6
Wait(500)
END

DO WHILE True = True


PROCEDURE CheckConnection()

xStatus is numeric
xStatus = ServerSettingsV2()
IF xStatus <> 0 THEN
ChangeLight(False)
ELSE
ChangeLight(True)
END


PROCEDURE ChangeLight(bConnected is boolean)


SWITCH bConnected
CASE True:
WIN_Main.IMG_ServerConnectionRed..Visible = False
WIN_Main.IMG_ServerConnectionGreen..Visible = True
gbIsConnected = True
WIN_Main.STC_ConnectionStatus..Visible = True
WIN_Main.STC_ConnectionStatus..Caption = "Connected"

CASE False
WIN_Main.IMG_ServerConnectionRed..Visible = True
WIN_Main.IMG_ServerConnectionGreen..Visible = False
gbIsConnected = False
WIN_Main.STC_ConnectionStatus..Visible = True
WIN_Main.STC_ConnectionStatus..Caption = "Offline"

OTHER CASE

END

Now, I am sure this isn't the most efficient way to accomplish this. I'm
still very much a beginner at programming. However, as you can see the
end result of this thread is changing UI elements on the main window.

Maybe what I'm calling a thread isn't actually a secondary thread?
Miembro registrado
105 mensajes
Publicado el 04,marzo 2015 - 15:24
After messing with it for a little bit this morning, it looks more like the issue I'm having is with figuring out how to reference controls on internal windows from procedures not on that window.

With normal windows I've been using <Window Name>.<Control Name..<Property> = <whatever>
It doesn't appear that the same syntax works with internal windows.
Miembro registrado
105 mensajes
Publicado el 04,marzo 2015 - 16:42
Thanks again for the advice Fabrice.

I'll figure out how to make it work as you've suggested.