none
Waitable object for IPC RRS feed

  • Question

  • Hi,

    Within one process, I'm using Manual/AutoResetEvents, but what is a waitable object that can be set from a different process? I have no problem using a Mutex which inherits from WaitHandle, but it has no Set() method.

    FW 3.5


    Armin

    Monday, June 18, 2012 2:17 PM

Answers

  • This is my solution narrowed down. Missing is UIManager.DoneEvent: It is set at the end of the UI thread's main function. And UIManager.BringMainWindowToFront: What it's name says. The implementation is application dependent.

    Imports System.Threading
    
    Friend Class MainThread
    
       Public Shared Sub Main(ByVal args As String())
    
          Const AppGuid As String = "{1ACC3CD3-2F81-47b1-9165-1E9BDE25C7E9}"
    
          Dim createdNew As Boolean
          Dim mux As Mutex
    
          mux = New Mutex(True, AppGuid, createdNew)
    
          Try
             Dim ActivationEvent As EventWaitHandle
             Dim waithandles As WaitHandle()
    
             ActivationEvent = New EventWaitHandle(False, EventResetMode.AutoReset, AppGuid & ".Activate")
    
             If Not createdNew Then
                ActivationEvent.Set()
                Return
             End If
    
             'Start UI Thread here
             '....
    
             waithandles = New WaitHandle() {UIManager.DoneEvent, ActivationEvent}
    
             Do
                Dim Index = WaitHandle.WaitAny(waithandles)
    
                Select Case Index
                   Case 0
                      Exit Do
                   Case 1
                      UIManager.BringMainWindowToFront()
                End Select
             Loop
    
          Finally
             If createdNew Then
                mux.ReleaseMutex()
             End If
          End Try
    
       End Sub
    
    End Class
    


    Armin

    • Marked as answer by Armin Zingler Monday, June 18, 2012 7:36 PM
    Monday, June 18, 2012 7:36 PM

All replies

  • Threading.Mutex and Threading.Semaphore provide constructors with names, and this gives you a way for a thread in one process to block (wait) until a thread in another process releases it.  So, use named mutexes for one-at-a-time access to an IPC resource, and use named semaphores to indicate when a send operation has been done (ie to release the other thread to read what was sent).  I think this will give you all you need.

    Monday, June 18, 2012 2:52 PM
  • Named events are also possible for IPC.

    Jose R. MCP
    Code Samples

    Monday, June 18, 2012 2:53 PM
  • Threading.Mutex and Threading.Semaphore provide constructors with names, and this gives you a way for a thread in one process to block (wait) until a thread in another process releases it.  So, use named mutexes for one-at-a-time access to an IPC resource, and use named semaphores to indicate when a send operation has been done (ie to release the other thread to read what was sent).  I think this will give you all you need.

    Thanks for your reply.

    I'm not sure how to do it. What I already did is holding a Mutex during the lifetime of the application to prevent the app from being started twice. At startup, I acquire the mutex (using a constant GUID as the name). If it has not been created new, I know that there's an instance already running, and the second instance exits. What I want to add now is sending a message to the first instance, telling it to restore it's main window. Of course, this can happen multiply times as the user might try to start a second instance many times.

    @Jose, what do you mean? I didn't find a NamedEvent class. :) I've browsed the object browser but didn't find anything related. The documentation (that I can handle usually well), doesn't seem to reveal anything, too. Or I've missed it.


    Armin

    Monday, June 18, 2012 3:48 PM
  • I see.  Well, it seems that it is only possible by P/Invoking then.  the CreateEvent() function clearly allows for a name.

    Jose R. MCP
    Code Samples

    Monday, June 18, 2012 3:56 PM
  • In your single process app, you could probably get things to work with one waitable object, but life is more complicated with multiple processes.  Here is a design for a single server process serving multiple client processes, but serving them one at a time.  For this to work, you need 2 mutexes (server and client) and 2 semaphores (server and client).  Lets call them ms, mc (the mutexes), ss, and sc (the semaphores).  The logic is shown in the insert below.  In general, the mutexes are used to seize a resource.  In this example, sm assures that there is only one server in existence, and cm assures that only one client runs at a time.  The semaphores are used to indicate across processes that something useful has happened.  ss released means that the client has written and the now unblocked server can read.  sc released means that the server has written and the now unblocked client can read.  Depending on your rules, you may need more or fewer waitable objects, but this single threaded client server design requires 4.  It is suitable, for example, for transaction-like IPC via memory mapped files.

    server logic: ms.waitone ' become the only server while processing continues ss.waitone ' wait until a client has sent data read, do stuff, write ' do what he wanted sc.release ' release the client to read server's response end while ms.releasemutex ' server no longer exists

    client logic: mc.waitone ' block until our turn to be client write ' send to server ss.release ' release the server sc.waitone ' wait for response read ' read response mc.releasemutex ' release unblocks the next client


    Monday, June 18, 2012 5:07 PM
  • Sorry, I didn't see this:

    "What I want to add now is sending a message to the first instance, telling it to restore it's main window. Of course, this can happen multiply times as the user might try to start a second instance many times."

    The 4 waitable object design may be overkill for your needs.  To make an event visible across processes, you could just use a named semaphore.  A new dedicated thread in your main process would wait on this semaphore, and when released, it would raise an event in your main app (watch out for multi-thread form issues here).  If you had 4 different triggers instead of one, you could have 4 semaphores.  One listener, potentially many signalers.  In this case, there is no IPC in the sense of data flow - just IPC triggers, if you see what I mean.

    Monday, June 18, 2012 5:27 PM
  • Before trying to understand your approach, I just stumbled across System.Threading.EventWaitHandle (base classe of manual/autoresetevent), and one of it's ctors expects a name, so it seems to be the "named (system) event" you were talking about. ......... Tried it: Yep, works. Don't know why I didn't see it (consciously) before.

    Thanks, problem solved. :-)

    I'll post the main function in case anyone's interested. (Before, I'll have to fix a different problem related to marshalling to the UI thread.)


    Armin

    Monday, June 18, 2012 6:43 PM
  • This is my solution narrowed down. Missing is UIManager.DoneEvent: It is set at the end of the UI thread's main function. And UIManager.BringMainWindowToFront: What it's name says. The implementation is application dependent.

    Imports System.Threading
    
    Friend Class MainThread
    
       Public Shared Sub Main(ByVal args As String())
    
          Const AppGuid As String = "{1ACC3CD3-2F81-47b1-9165-1E9BDE25C7E9}"
    
          Dim createdNew As Boolean
          Dim mux As Mutex
    
          mux = New Mutex(True, AppGuid, createdNew)
    
          Try
             Dim ActivationEvent As EventWaitHandle
             Dim waithandles As WaitHandle()
    
             ActivationEvent = New EventWaitHandle(False, EventResetMode.AutoReset, AppGuid & ".Activate")
    
             If Not createdNew Then
                ActivationEvent.Set()
                Return
             End If
    
             'Start UI Thread here
             '....
    
             waithandles = New WaitHandle() {UIManager.DoneEvent, ActivationEvent}
    
             Do
                Dim Index = WaitHandle.WaitAny(waithandles)
    
                Select Case Index
                   Case 0
                      Exit Do
                   Case 1
                      UIManager.BringMainWindowToFront()
                End Select
             Loop
    
          Finally
             If createdNew Then
                mux.ReleaseMutex()
             End If
          End Try
    
       End Sub
    
    End Class
    


    Armin

    • Marked as answer by Armin Zingler Monday, June 18, 2012 7:36 PM
    Monday, June 18, 2012 7:36 PM