Sign in to follow this  
Followers 0
martin

_Singleton doesn't always work

17 posts in this topic

Here is an example where I find that _Singleton doesn't appear to work every time. Compile the script below and try running a few instances.

The mutex created by each instance should not already exist and is used for the window title, so every window should have a different title, but I get duplicated titles. Sometimes I might get 5 or 6 with the same, sometimes I might get 5 different titles then duplictes of the first and the second.

I'm using AutoIt production 3.3.0.0, XP SP3

Maybe I'm missing something.

#include <misc.au3>
#include <sendmessage.au3>
Global Const $WM_BROADCAST = 0xFFFF

Global $gui = GUICreate("Singleton group", 250, 70)
GUISetState()


Local  $inst = 1
$Title = "SingletonMutex_" & $inst
While _Singleton($Title,1) = 0
    $inst += 1
    $Title = "SingletonMutex_" & $inst

    sleep(50)
WEnd
WinSetTitle($Gui, "", $Title)

;get a message number to use
$MyMsg1 = RegisterWindowMessage("Singletonmanywindows")
GUIRegisterMsg($MyMsg1, "AllExit")

While 1
    if GUIGetMsg() = -3 then _SendMessage($WM_BROADCAST,$MyMsg1)

WEnd


Func AllExit();so you don't have to close each window manually
    Exit
EndFunc


Func RegisterWindowMessage($sText)
    Local $aRet = DllCall('user32.dll', 'int', 'RegisterWindowMessage', 'str', $sText)
    Return $aRet[0]
EndFunc   ;==>RegisterWindowMessage

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Your example works fine for me. Anyway, for this purpose is better to use Semaphores.

Example (Idea by trancexx)

#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>

Global Const $WM_BROADCAST = 0xFFFF
Global Const $Count = 100

Global $MyMsg = _WinAPI_RegisterWindowMessage('MyMsg')
Global $Quit = False

GUIRegisterMsg($MyMsg, '_Quit')

$hSemaphore = _WinAPI_CreateSemaphore('MySemaphore', 0, $Count)
$Index = _WinAPI_ReleaseSemaphore($hSemaphore) + 1
$hSemaphore = _WinAPI_CreateSemaphore('MySemaphore', 0, $Count)

_MyGUI($Index)

_WinAPI_ReleaseSemaphore($hSemaphore)
_WinAPI_FreeHandle($hSemaphore)

Func _MyGUI($sTitle)
    GUICreate($sTitle)
    GUISetState()
    Do
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then
            _SendMessage($WM_BROADCAST, $MyMsg)
            ExitLoop
        EndIf
    Until $Quit
EndFunc   ;==>_MyGUI

Func _Quit()
    $Quit = 1
EndFunc   ;==>_Quit

WinAPIEx.au3

Edited by Yashied

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Your example works fine for me. Anyway, for this purpose is better to use Semaphores.

Example (Idea by trancexx)

#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>

Global Const $WM_BROADCAST = 0xFFFF
Global Const $Count = 100

Global $MyMsg = _WinAPI_RegisterWindowMessage('MyMsg')
Global $Quit = False

GUIRegisterMsg($MyMsg, '_Quit')

$hSemaphore = _WinAPI_CreateSemaphore('MySemaphore', 0, $Count)
$Index = _WinAPI_ReleaseSemaphore($hSemaphore) + 1
$hSemaphore = _WinAPI_CreateSemaphore('MySemaphore', 0, $Count)

_MyGUI($Index)

_WinAPI_ReleaseSemaphore($hSemaphore)
_WinAPI_FreeHandle($hSemaphore)

Func _MyGUI($sTitle)
    GUICreate($sTitle)
    GUISetState()
    Do
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then
            _SendMessage($WM_BROADCAST, $MyMsg)
            ExitLoop
        EndIf
    Until $Quit
EndFunc   ;==>_MyGUI

Func _Quit()
    $Quit = 1
EndFunc   ;==>_Quit

WinAPIEx.au3

The semaphore method works for me, thanks for the example Yasied. But I don't undedrstand why the _Singleton method doesn't work. The attached picture shows a typical example, maybe there is something wrong with my PC.

post-3602-12509737184538_thumb.png

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

The semaphore method works for me, thanks for the example Yasied. But I don't undedrstand why the _Singleton method doesn't work. The attached picture shows a typical example, maybe there is something wrong with my PC.

Did you open them by hand or use a script to open them?

If you open them with a script: These function are not thread safe there for if you open them rapidly it overwrite each other.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Share this post


Link to post
Share on other sites

Wow, maybe Sleep(200) instead Sleep(50)? CreateMutex too slow.

I put the sleep(50) in the loop after I getting several titles the same but different to the first one, but a sleep inside the loop won't help if _SIngleton doesn't think even the first mutex exists.

But I found that any one of these changes do work-

A. sleep(200) after GuiSetState and before the first _Singleton is called. ( If I take the sleep out again and I am back to many windows with the same title.)

B. search for a new mutex at the start of the script, ie before the GuiCreate. Works fine without any delays.

C. Create the gui but don't show it. Find the new mutex, show the gui. Works with no delays

So I think there might be something about showing a gui that affects the CreateMutex function for a short time.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I put the sleep(50) in the loop after I getting several titles the same but different to the first one, but a sleep inside the loop won't help if _SIngleton doesn't think even the first mutex exists.

But I found that any one of these changes do work-

A. sleep(200) after GuiSetState and before the first _Singleton is called. ( If I take the sleep out again and I am back to many windows with the same title.)

B. search for a new mutex at the start of the script, ie before the GuiCreate. Works fine without any delays.

C. Create the gui but don't show it. Find the new mutex, show the gui. Works with no delays

So I think there might be something about showing a gui that affects the CreateMutex function for a short time.

Nice. So the problem is solved. But what is interesting - your example works fine for me for all combinations.

Edited by Yashied

Share this post


Link to post
Share on other sites

>_< that means I am right, just in the wrong place but it's basically the same thing.

I don't follow what you are saying but if it helps, I did what I think I said earlier. I compiled the script then ran the exe, moved the gui a bit, ran the exe again, moved the gui a bit and so on. I don't see anything that you are right about since I don't understand what you are saying when you said they overwrite each other. The fact that sometimes I got a title with 1 at the end and sometimes with 4 at the end means that the mutex 1 to 3 must exist, but despite that, I might get a title with 1 again later. If you understand why that happens I would be interested to have it explained to me.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Two or more processes can call CreateMutex to create the same named mutex. The firstprocess actually creates the mutex, and subsequent processes withsufficient access rights simply open a handle to the existing mutex.This enables multiple processes to get handles of the same mutex, whilerelieving the user of the responsibility of ensuring that the creatingprocess is started first. When using this technique, you should set thebInitialOwner flag to FALSE; otherwise, it can be difficult to be certain which process has initial ownership.

http://msdn.microsoft.com/en-us/library/ms682411%28VS.85%29.aspx

From Misc.au3:

$handle = DllCall("kernel32.dll", "int", "CreateMutex", "ptr", $pSecurityAttributes, "long", 1, "str", $sOccurenceName)

Try to replace 1 to 0.

Edited by Yashied

Share this post


Link to post
Share on other sites

http://msdn.microsoft.com/en-us/library/ms682411%28VS.85%29.aspx

From Misc.au3:

$handle = DllCall("kernel32.dll", "int", "CreateMutex", "ptr", $pSecurityAttributes, "long", 1, "str", $sOccurenceName)

Try to replace 1 to 0.

Yes, I wondered about that too and I tried 1 and 0 before I posted the problem. I have just tried it again in case my memory failed but it doesn't make any difference. >_<

You would expect that the reason is that the call to CreateMutex creates an error which is not $ERROR_ALREADY_EXISTS but I've tried a version which lists the error number from GetLastError and the errors are either $ERROR_ALREADY_EXISTS or 0. The problem is that the error of zero occurs when it should not, or at least not as I understand it.

I think that it is very rare that anyone wants to use _Singleton after creating a gui so I'm not going to worry about it, though I have made a note of in in a function I use to test if a mutex exists.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Oops, I didn't read the MSDN (am wrong at last lol)(never use this in c# or Autoit only used the Object Lock)

Anyway your example does not give any problem the windows comes up to 1 2 3 4 5 even I remove the sleep and so.

From the thread it seem that you are the only one with the problem?

Share this post


Link to post
Share on other sites

Oops, I didn't read the MSDN (am wrong at last lol)(never use this in c# or Autoit only used the Object Lock)

Anyway your example does not give any problem the windows comes up to 1 2 3 4 5 even I remove the sleep and so.

From the thread it seem that you are the only one with the problem?

@Martin: I have the same setup (XP SP3) and experience exactly what your original post describe with both the production and latest beta of AutoIt.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

This is bad.

And if you run something like this:

#include <misc.au3>

; 1.
Global $hGUI = GUICreate("Singleton group", 250, 70, 100, 100)
GUISetState()


Global $iInst = 1
Global $Title = "SingletonMutex_" & $iInst

While _Singleton($Title, 1) = 0
    $iInst += 1
    $Title = "SingletonMutex_" & $iInst
WEnd

WinSetTitle($hGUI, "", $Title)



; 2.
Global $hGUI1 = GUICreate("Singleton group", 250, 70, 200, 200)
GUISetState()


$iInst = 1
$Title = "SingletonMutex_" & $iInst

While _Singleton($Title, 1) = 0
    $iInst += 1
    $Title = "SingletonMutex_" & $iInst
WEnd

WinSetTitle($hGUI1, "", $Title)


; 3.
Global $hGUI2 = GUICreate("Singleton group", 250, 70, 300, 300)
GUISetState()


$iInst = 1
$Title = "SingletonMutex_" & $iInst

While _Singleton($Title, 1) = 0
    $iInst += 1
    $Title = "SingletonMutex_" & $iInst
WEnd

WinSetTitle($hGUI2, "", $Title)



; 4.
Global $hGUI3 = GUICreate("Singleton group", 250, 70, 400, 400)
GUISetState()


$iInst = 1
$Title = "SingletonMutex_" & $iInst

While _Singleton($Title, 1) = 0
    $iInst += 1
    $Title = "SingletonMutex_" & $iInst
WEnd

WinSetTitle($hGUI3, "", $Title)



While 1
    If GUIGetMsg() = -3 Then Exit
WEnd

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

This is bad.

And if you run something like this:

I've tried this '4 online' version. It doesn't work 100% either. (Tried from Scite or compiled, beta or std).

When several runs are active, I get unexpected behavior (without closing anything):

1,2,3,4 then 5,6,7,8 then 2,9,10,11 then 12,13,1,1 then 14,15,16,2

Another try:

1,2,3,4 then 5,6,7,8 then 9,10,11,12 then 13,14,15,1 then 16,17,3,18 then 19,8,5,20

Looks like the "numbers" in the increasing natural sequence are never missed but other mutexes "numbers" get interleaved with them which are picked up more or less randomly in the already used "numbers". I know these numbers are actually strings, but I fail to understand how this is at all possible.

I'll try on more PCs here later and report. I have several XP x86 SP3 desktops and one Vista x86 notebook.

EDIT:

After various tries, it seems just like the faster the PC is, the more errors occurs but it's difficult to pose this as a rule. I've even had sequences created out of order, like 61, 63, 64, 62 on the slow Vista notebook.

Launching the .exe from the network seemed to slow down the rate of errors (launches slower due to network and less overall caching).

There is something wrong with the call. I suspect that if the underlying Windows mutex machinery was that buggy, then we couldn't even boot a system nor have anything serious done.

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

I did manage to reproduce it with this code:

#NoTrayIcon

Opt("MustDeclareVars", 1)

#include <Misc.au3>

Global $iMaxX = @DesktopWidth - 250
Global $iMaxY = @DesktopHeight - 150

Global $hGUI
Global $iInst = 1
Global $iStartError
Global $sFirstErrorGUIHandle

For $i = 1 To 100

    $hGUI = GUICreate("Error", 250, 70, Random(0, $iMaxX), Random(0, $iMaxY))
    GUISetState()

    Global $Title = "SingletonMutex_" & $iInst

    While _Singleton($Title, 1) = 0
        $iInst += 1
        $Title = "SingletonMutex_" & $iInst
    WEnd

    If $iInst = $i Then
        WinSetTitle($hGUI, "", $Title)
    Else
        If $iStartError = 0 Then
            $iStartError = 1
            $sFirstErrorGUIHandle = $hGUI
            WinSetTitle($hGUI, "", "First error with $i = " & $i)
            Beep(500, 500)
        Else
            WinSetTitle($hGUI, "", "Error with $i = " & $i)
        EndIf
    EndIf

    $iInst = 1

Next

If $sFirstErrorGUIHandle Then
    WinMove($sFirstErrorGUIHandle, "", (@DesktopWidth - 250) / 2, (@DesktopHeight - 70) / 2)
    WinSetOnTop($sFirstErrorGUIHandle, "", 1)
    WinFlash($sFirstErrorGUIHandle, "", 8, 80)
EndIf

While 1
    If GUIGetMsg() = -3 Then Exit
WEnd

It shouldn't beep. Don't run parallel (makes no sense).

It beeps randomly for me.

Close one to close all.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

I did manage to reproduce it with this code:

It shouldn't beep. Don't run parallel (makes no sense).

It beeps randomly for me.

Close one to close all.

Thank you for your interest in this. I don't really need his feature myself but I also try to have a better AutoIt whenever possible.

The results are intriguing.

My PCs are as follows:

a) two completely _identical_ PCs (same hardware and installed software) one never beeps while the other always beeps at low GUI instance number (X < 10)

>_< two highly comparable PCs (same MSI MB, same slow AMD Athlon) one never beeps while the other always beeps at much higher GUI instance (30 < X < 60)

d) a really fast PC: always beeps at low GUI instance number (X < 10)

All five above desktops share the exact same (shame on me!) XP x86 SP3 Pro Corp. with all latest patches from MS.

c) a slow notebook running Vista x86 : did beep only once at #95 and never again.

I tried increasing the loop from 100 to 250 but it didn't change anything on all machines.


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0