Creating Single and Limited Instance Applications






3.05/5 (9 votes)
Using operating system level objects to implement a single and limited instance application
Introduction
I needed to implement a single and limited instance application as a part of my project. I searched a lot on the internet, but it proved to be like finding a chocolate inside an egg. Mainly, this problem was about synchronizing access to the resources used by the application. After searching on MSDN, I found a way to do so simply as well as effectively. The solution I managed to develop involves use of operating system level objects, say, kernel objects.
This article explains about these objects, which I used in my application to get my job done. These objects are, namely:
Mutex
Semaphore
Of course, there is one more kernel object that I would like to mention here, which is an Event
object. We can use Event
objects to notify multiple threads across application domains, but I'm not going to discuss them in this article.
Background
As a starting point, I found some clues from the article published on this site about single instance applications.
Using the Code
Single Instance Applications
First, I am going to show you how we can create a single instance application using the Mutex
class provided in .NET Framework 2.0. This object is mainly used to lock data and resources across application domains and process boundaries. When we create a Mutex
object in our application, it is assigned a unique handle by the kernel of our operating system. The following is the code to create a single instance application:
'Define name and reference for Mutex object
Dim mt As Mutex = Nothing
Const Name As String = "MyMutex"
'Check for a Mutex object with the same name already
'exist in any running application domain
Try
mt = Mutex. OpenExisting(Name)
Catch e As WaitHandleCannotBeOpenedException
'Catch exception here if there is no Mutex object exist with a given name
'Console. WriteLine(e. Message)
Catch ex As Exception
'Catch any other exception
End Try
'If there is no Mutex object exist with same name create one
If mt Is Nothing Then
mt = New Mutex(True, Name)
Else
'Close Mutex here and our application too
'because already one instance
'of Mutex is running and we dont need more
'instance running at the same time.
mt. Close()
'Write application closing code here This will just simply return
Return
End If
By using the OpenExisting()
method of the Mutex
object, you can check for the existence of any Mutex
object with the same name. Note that this method will throw an exception of "No handle of the given name exists" if there is no Mutex
object with the given name existing. So, it's better to handle this exception in our code.
Limited Instance Application
To create a limited instance application, you need to allow access to resources to the set number of threads in the same or across application domains or process domains. In such situations, our Semaphore
kernel object comes into the picture. This object uses a limited number of slots for resources at once. For the sake of our application, we consider a slot as an instance of our application. When these slots reach the maximum number, remaining instances of the application will not be allowed to run. Using the following code, you can create a maximum of 3 application instances at the same time:
'Define name and reference for Semaphore object
Dim Sem As Semaphore = Nothing
Const Name As String = "MySemaphore"
'Check for a Semaphore object with the same name already
'exist in any running application domain
Try
Sem = Semaphore. OpenExisting(Name)
Catch e As WaitHandleCannotBeOpenedException
'Catch exception here if there is no semaphore object
'exist with a given name
'Console. WriteLine(e. Message)
Catch ex As Exception
End Try
'If there is no semaphore object exist with the same name,
'create it with minimum and maximum slot
If Sem Is Nothing Then
Sem = New Semaphore(1, 5, Name)
Else
'You can release slot here to use by another instance by closing
'this instance here
'Or you can close instance if maximum number of instance reached
Sem. Release()
'Write application closing code here. This will just simply return
Return
End If
To free a slot, you can use the Release()
method of the Semaphore
object. Additionally, you can specify the number of slots to release in this method. When this method is used without parameters, it means that it will release one slot per instance of an application. Based on the currently running number of instances, you can check for the instance termination. The rest of the thing is the same as in a Mutex
object, like checking for an existing Semaphore
with named Semaphore
and exception handling.
Points of Interest
Even though these objects are helpful in creating single and limited instance applications, they are mainly used for thread synchronization across application and process domains. One more thing that I must mention is that these objects are kernel mode objects, so they come with overhead. I mean that they are heavyweight objects. So, I suggest you use them while keeping your eye on the performance of your application and the functionality you need to achieve.
History
- 14 September, 2007 -- Original version posted