65.9K
CodeProject is changing. Read more.
Home

Creating Single and Limited Instance Applications

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.05/5 (9 votes)

Sep 14, 2007

CPOL

3 min read

viewsIcon

46042

downloadIcon

544

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:

  1. Mutex
  2. 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