Page 1 of 1

PostEvent in DLL fails when procedure called from a thread

Posted: Mon May 02, 2016 6:16 pm
by Olby
Hi,

Can anyone please explain why the code below fails:

Code: Select all

CompilerIf #PB_Compiler_ExecutableFormat=#PB_Compiler_DLL
	
	Procedure thread(*p) ; api func
		PostEvent(#PB_Event_FirstCustomValue)
		Delay(5000)
		PostEvent(#PB_Event_FirstCustomValue+1)
	EndProcedure
	
	Procedure.i run() ; wait thread func
		If OpenWindow(0,0,0,320,240,"Module Window",#PB_Window_SystemMenu)
			If CreateThread(@thread(),0)
				Repeat
					Protected event.i=WaitWindowEvent()
					If event=#PB_Event_FirstCustomValue+1
						ProcedureReturn 2001
					EndIf
				ForEver
			EndIf
		EndIf
	EndProcedure
	
	ProcedureDLL.i test() ; run func
		ProcedureReturn run()
	EndProcedure

CompilerElse
	
	Procedure calltest(*p) ; module caller thread
		Debug "Calling test() in dll"
		Debug CallFunction(0,"test")
	EndProcedure
	
	If OpenLibrary(0,"_test.dll")
		If OpenWindow(0,0,0,800,600,"Window",#PB_Window_SystemMenu)
			Debug "Waiting for 2001 response in 5 seconds"
			
			test.b=1
			
			If test=1
				calltest(0)
			Else
				If CreateThread(@calltest(),0)
					Repeat 
						WaitWindowEvent()
						Delay(1000)
						Debug "..."
					ForEver
				EndIf
			EndIf
			
		EndIf
	EndIf
	
CompilerEndIf
Flags: ThreadSafe, Unicode, WinXP & OnError

First compile a DLL to _test.dll, then switch back to regular executable mode and run the code again.

If test =1 everything is fine. We call the dll function directly and after 5 seconds the internal postevent signals the DLL func to return 2001 back to the main process.

Now the issue I have is with test <>1 mode. In this case the DLL function is called from a thread within the main process. And it will never return because the PostEvent(#PB_Event_FirstCustomValue+1) in the DLL will never reach its destination and the DLL function will keep on running for ever.

Is this a PB bug or there is an issue with clashing event streams or something similar?

Thanks!

Re: PostEvent in DLL fails when procedure called from a thre

Posted: Tue May 03, 2016 1:38 pm
by Danyfirex
Hello. If you're createing a thread safe library you must use PostThreadMessage and pass the thread id to the subthread.

Code: Select all

Global threadid=0

Procedure thread(*p) ; api func
      PostEvent(#PB_Event_FirstCustomValue)
      Delay(5000)
      ;PostEvent(#PB_Event_FirstCustomValue+1)
      PostThreadMessage_(*p,#PB_Event_FirstCustomValue+1,0,0)
 EndProcedure
   
   Procedure.i run() ; wait thread func
     If OpenWindow(0,0,0,320,240,"Module Window",#PB_Window_SystemMenu)
       threadid=GetCurrentThreadId_()
         If CreateThread(@thread(),threadid)
            Repeat
               Protected event.i=WaitWindowEvent()
               If event=#PB_Event_FirstCustomValue+1
                  ProcedureReturn 2001
               EndIf
            ForEver
         EndIf
      EndIf
   EndProcedure
   
   ProcedureDLL.i test() ; run func
      ProcedureReturn run()
   EndProcedure

other alternative if you want to use your dll code is compiling your dll as not thread safe. that way you don't need PostThreadMessage




Saludos

Re: PostEvent in DLL fails when procedure called from a thre

Posted: Tue May 03, 2016 3:54 pm
by Olby
That seems like a good solution. So my guess was right each thread has its own event queue. Thanks, Danyfirex.

Re: PostEvent in DLL fails when procedure called from a thre

Posted: Tue May 03, 2016 4:21 pm
by Danyfirex
You're Wellcome.

Saludos