Topaz Filer: if you use e-mail for business, we can save you money and decrease your risk.
Synchronizing processes in C#
Messages   Related Types
This message was discovered on microsoft.public.dotnet.languages.csharp.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.

Chris B (VIP)
I have the following situation:

Process 1 creates Process 2 (using Process.Start(startInfo)
Process 1 needs to wait until Process 2 is initialized before Process 1 can continue to execute
Both processes are non-GUI processes.

The problem that I am running into is that the Process.Start(startInfo) returns immediately to Process 1. Therefore, process 1 does not wait on its own for Process 2 to initialize.

Process 2 can take a few seconds to intialize. Process 1 needs to halt its execution until Process 2 is initialized. How can process 1 and 2 signal eachother to accomplish what I'm after?

In process 1 I tried using a Mutex:

Process process = Process.Start(startInfo);

if (process != null)
{
Mutex m = new Mutex(false, "Mutex");
m.WaitOne();
...
}

Process 2:

Main...
{
bool mutexWasCreated = false;
Mutex m = new Mutex(true, "Mutex", out mutexWasCreated);
if (mutexWasCreated)
{
...
m.ReleaseMutex();
}
}

this doesn't come close to working because process 1 gets the mutex before process 2 can acquire the lock. What I need is the ability to have process 1 wait on a mutex, have process 2 acquire the mutex lock, do its initialization, then release the mutex, then process 1 resumes execution.

I have gotten the above to work in C++ using the CreateEvent API. Process 1 creates an unsignaled event, process 1 launches process 2, process 1 waits on the event, process 2 does its thing, process 2 signals the event, process 1 continues.

How can I do this in C#?

Thanks!

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
David Levine
You can use P/Invoke to access the Win32 CreateEvent API to create named
events. I created this test app fairly quicklly that seems to work...

in project 1

using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool
bManualReset,
bool bInitialState, string lpName);

[DllImport("kernel32.dll")]
static extern bool SetEvent(IntPtr hEvent);

[DllImport("kernel32.dll")]
static extern bool ResetEvent(IntPtr hEvent);

[DllImport("kernel32.dll", SetLastError=true)]
static extern int CloseHandle(IntPtr hObject);

const int ERROR_ALREADY_EXISTS = 183;

/// <summary>
///
/// </summary>
[STAThread]
static void Main(string[] args)
{
string file =
@"..\..\..\ConsoleApplication2\bin\debug\ConsoleApplication2.exe";
if ( !System.IO.File.Exists(file) )
{
Print("Unable to locate file {0}",file);
return;
}
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo(file,"2");
p.StartInfo = psi;

IntPtr handle;
bool createdNew;
if ( !CreateManagedEvent(out handle,out createdNew) )
{
Print("Error creating named event.");
return;
}

if ( !createdNew )
{
Print("App2 already running. Press any key to exit...");
Console.ReadLine();
return;
}
else
{
Console.WriteLine("Starting other app");
ManualResetEvent _evt = new ManualResetEvent(false);
_evt.Handle = handle;
_evt.Reset();
DateTime start = DateTime.Now;
p.Start();

Print("Waiting....");
_evt.WaitOne(TimeSpan.FromSeconds(15),false);
TimeSpan elapsed = DateTime.Now - start;
Print("Done waiting; it took {0} seconds...",elapsed.Seconds);
}
Print("All done");

}

/// <summary>
/// Creates a named event in the win32 space. This is a manual
/// reset event that is initially not signalled.
/// </summary>
/// <param name="handle"></param>
/// <param name="createdNew">true if it created a new one, false if it
opened an existing one</param>
/// <returns>true if it succeeds, otherwise false</returns>
static bool CreateManagedEvent(out IntPtr handle,out bool createdNew)
{
createdNew = false;
handle = CreateEvent(IntPtr.Zero, true,false, "MyNamedEvent");
int error = Marshal.GetLastWin32Error();
if ( handle == IntPtr.Zero )
return false;
createdNew = (error != ERROR_ALREADY_EXISTS);
return true;
}

static void Print(string format,params object[] args)
{
string msg = string.Format(format,args);
Trace.WriteLine(msg);
Console.WriteLine(msg);
}
}
}

in project 2

using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class2
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool
bManualReset,
bool bInitialState, string lpName);

[DllImport("kernel32.dll")]
static extern bool SetEvent(IntPtr hEvent);

[DllImport("kernel32.dll")]
static extern bool ResetEvent(IntPtr hEvent);

[DllImport("kernel32.dll", SetLastError=true)]
static extern int CloseHandle(IntPtr hObject);

const int ERROR_ALREADY_EXISTS = 183;

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
IntPtr handle;
bool createdNew;
if ( !CreateManagedEvent(out handle,out createdNew) )
{
Print("Error creating named event.");
return;
}

if ( createdNew )
{
Print("App1 not running yet, exiting after a 10 second wait...");
Thread.Sleep( TimeSpan.FromSeconds(10) );
return;
}
Print("Sleeping for a few seconds...");
Thread.Sleep( TimeSpan.FromSeconds(2) );
Print("Done sleeping, setting event...");
ManualResetEvent _evt = new ManualResetEvent(false);
_evt.Handle = handle;
_evt.Set();
Print("Sleeping for 10 more seconds...");
Thread.Sleep( TimeSpan.FromSeconds(10) );
Print("Done");
}
/// <summary>
/// Creates a named event in the win32 space. This is a manual
/// reset event that is initially not signalled.
/// </summary>
/// <param name="handle"></param>
/// <param name="createdNew">true if it created a new one, false if it
opened an existing one</param>
/// <returns>true if it succeeds, otherwise false</returns>
static bool CreateManagedEvent(out IntPtr handle,out bool createdNew)
{
createdNew = false;
handle = CreateEvent(IntPtr.Zero, true,false, "MyNamedEvent");
int error = Marshal.GetLastWin32Error();
if ( handle == IntPtr.Zero )
return false;
createdNew = (error != ERROR_ALREADY_EXISTS);
return true;
}

static void Print(string format,params object[] args)
{
string msg = string.Format(format,args);
Trace.WriteLine(msg);
Console.WriteLine(msg);
}

}
}

"Chris B" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

own for Process 2 to initialize.
[Original message clipped]

signal eachother to accomplish what I'm after?
[Original message clipped]

1 wait on a mutex, have process 2 acquire the mutex lock, do its
initialization, then release the mutex, then process 1 resumes execution.
[Original message clipped]

on the event, process 2 does its thing, process 2 signals the event, process
1 continues.
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
Auto-following on Twitter
Ubuntu and XP on one “desktop”
 
    
AKA COOPERMAN (VIP)
Try using the following classes instead

AutoResetEvent
ManualResetEvent

Andy Cooper

"Chris B" wrote:

[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
David Levine
Those classes do not support named events which means they cannot be used
between processes.

"AKA COOPERMAN" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

own for Process 2 to initialize.
[Original message clipped]

signal eachother to accomplish what I'm after?
[Original message clipped]

process 1 wait on a mutex, have process 2 acquire the mutex lock, do its
initialization, then release the mutex, then process 1 resumes execution.
[Original message clipped]

1 waits on the event, process 2 does its thing, process 2 signals the event,
process 1 continues.
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
Outlook interop - stopping user properties appearing on Outlook message print
Seriously, why is “cut and paste” majorly newsworthy???
 
 
System.Console
System.DateTime
System.Diagnostics.Process
System.Diagnostics.ProcessStartInfo
System.Diagnostics.Trace
System.IntPtr
System.IO.File
System.Runtime.InteropServices.Marshal
System.Threading.AutoResetEvent
System.Threading.ManualResetEvent
System.Threading.Mutex
System.Threading.Thread
System.TimeSpan




Ad
BootFX
Reliable and powerful .NET application framework.
Recession Busting Bespoke Software
Get through the recession by investing in bespoke software to decrease costs and create commercial opportunities.
Other DN247 Network Sites
.NET 247
SQL Server Wins
Old Skool Developer
 
Copyright © AMX Software Ltd 2008-2009. Portions copyright © Matthew Baxter-Reynolds 2001-2009. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - .NET 247 is a member of the DN247 Network - 4.0.30129.1734