处理来自其他应用程序的事件

时间:2014-05-13 09:26:54

标签: c# process event-handling

Hellu

问题很简单,但答案似乎很多,而且很不清楚。

我如何在应用程序A中处理应用程序B发送的事件,以及如何在B中实现这些事件?知道B不知道A的存在。

让我们说B是一个类似批次的"程序的类型,在后面做事情,没有任何图形显示,A是很好的GUI (双关语)应该写消息B在对话框中发送给他。

我找到了有关此问题的有趣答案(例如this onethis one),但实际上没有人用C#的例子回答这个问题;充其量,他们重定向到一些外部工具。

我听说这是C#中的一个问题,但最后有没有一个干净的方法呢?感谢。

如果这可以缓解这个问题,那么让我们说A启动B(带有Process或其他东西),知道B也可以单独启动(在这种情况下,我不需要整个事件处理的东西)。

2 个答案:

答案 0 :(得分:5)

您可以使用MemoryMappedFileMutexEventWaitHandle的组合在流程之间进行管理。

以下示例显示了它的工作原理。在实际代码中,producer()方法与consumer()方法的应用程序不同,但这用于说明实现:

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();
        }
    }
}

重要提示:此实现不使用队列,因此如果消息在新消息到达之前未处理消息,则消息可能会丢失消息。

如果您不能错过任何消息,则必须使用某种排队实现,例如MSMQ

但是,您也可以考虑使用Windows Communications Foundation,它允许您在另一个进程中调用远程方法 - 但这可能需要在进程之间实现比您想要的更多耦合。

最后,另一种可能性是使用Named Pipe。我实际上认为这对你来说可能是最好的解决方案。

有一个Microsoft示例在此处使用命名管道显示服务器和客户端IPC:http://msdn.microsoft.com/en-us/library/bb546085%28v=vs.110%29.aspx

答案 1 :(得分:0)

取决于您的方案会有多复杂。 您可以使用进程间通信,甚至可以使用2个应用程序写入/读取的简单文件(或db表)(您需要同步访问它)。