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!
|
|
|
| |
|
|
| |
| |
| 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]
|
|
|
| |
|
| |
|
| |
| AKA COOPERMAN (VIP) |
Try using the following classes instead
AutoResetEvent ManualResetEvent
Andy Cooper
"Chris B" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| 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]
|
|
|
| |
|
| |
|
|
|
|
|
|