سؤال

Hellu

The question is simple, yet the answers seem to be various and pretty unclear.

How can I, in an application A, handle events sent by an application B, and how to implements those events in B? Knowing that B has no idea of the existence of A.

Let's say B is a "batch-like" type of program, doing things in the back with no graphical display whatsoever, and A is the nice GUI (pun intended) that should write messages B sends him in a dialog or something.

I found interesting answers about this (like this one or this one), but none actually answers the issue with example for C#; at best, they redirect to some external tools.

I heard it was an issue in C#, but in the end, is there a clean way to do it? Thanks.

If that can ease the thing, let's say A launches B (with Process or something), knowing that B can also be launched alone (in which case, I don't need this whole event handling thing).

هل كانت مفيدة؟

المحلول

You could use a combination of MemoryMappedFile, Mutex and EventWaitHandle to manage this between processes.

The following example shows how it would work. In real code, the producer() method would be in a different application from the consumer() method, but this serves to illustrate an implementation:

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        void run()
        {
            Task.Run(() => consumer());
            Task.Run(() => producer());

            Console.WriteLine("Press <ENTER> to stop.");
            Console.ReadLine();
        }

        static void producer()
        {
            using (var mmf = MemoryMappedFile.CreateOrOpen("MyMapName", 1024))
            using (var view = mmf.CreateViewStream())
            {
                var writer = new BinaryWriter(view);
                var signal = new EventWaitHandle(false, EventResetMode.AutoReset, "MyEventName");
                var mutex = new Mutex(false, "MyMutex");

                for (int i = 0; i < 100; ++i)
                {
                    string message = "Message #" + i;

                    mutex.WaitOne();
                    writer.BaseStream.Position = 0;
                    writer.Write(message);
                    signal.Set();
                    mutex.ReleaseMutex();

                    Thread.Sleep(1000);
                }
            }
        }

        static void consumer()
        {
            using (var mmf = MemoryMappedFile.CreateOrOpen("MyMapName", 1024))
            using (var view = mmf.CreateViewStream())
            {
                var reader = new BinaryReader(view);
                var signal = new EventWaitHandle(false, EventResetMode.AutoReset, "MyEventName");
                var mutex = new Mutex(false, "MyMutex");

                while (true)
                {
                    signal.WaitOne();
                    mutex.WaitOne();
                    reader.BaseStream.Position = 0;
                    var message = reader.ReadString();
                    Console.WriteLine("Received message: " + message);
                    mutex.ReleaseMutex();
                }
            }
        }

        static void Main()
        {
            new Program().run();
        }
    }
}

IMPORTANT: This implementation does not use a queue, so it is possible for the consumer to miss messages if it does not process them before a new message arrives.

If you must not miss any messages, you would have to use some kind of queuing implementation instead, for example MSMQ.

However, you could also consider using Windows Communications Foundation, which allows you to call remote methods in another process - but that might require more coupling between processes than you want.

Finally, another possibility is to use a Named Pipe. I actually think this might be the best solution for you.

There's a Microsoft example showing server and client IPC using a named pipe here: http://msdn.microsoft.com/en-us/library/bb546085%28v=vs.110%29.aspx

نصائح أخرى

depends on how complex your scenario would get. You could use Interprocess communication or even some simple file (or db table) which would be written/read by the 2 apps (you'll need to sync access to it).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top