您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C#中具有进程间通信的Singleton应用程序

寒冰屋 发布时间:2020-05-17 11:21:54 ,浏览量:0

目录

介绍

概念化这个混乱

编码此混乱

  • 下载SingletonIPC.zip-4.5 KB
介绍

有时,您可能会在某个应用程序中没有必要两次启动主应用程序,但是您可能希望通过传递其他命令行参数来再次运行该应用程序。这样,您可以运行该应用程序,它将打开您的程序,然后您可以再次运行该应用程序,并将其他命令行信息传递给已运行的应用程序。例如,当您想让现有应用程序从命令行打开新文件时,这很有用。因此它像这样处理:

C:\Foo> MyApp myfile1.txt
C:\Foo> MyApp myfile2.txt myfile3.txt

在这种情况下,MyApp仅在第一次启动实际的应用程序。第二次,它检测到它已经在运行,并简单地将传入的命令行发送到已经运行的应用程序进行处理。

概念化这个混乱

为了提供此功能,我们对该应用程序有两个主要方面。

首先,该应用程序需要检测它是否已经在运行,并且根据它是否已经在运行,它将执行不同的操作。

其次,我们需要一种使两个进程进行通信的方法。在这种情况下,主应用程序将等待子序列启动产生的命令行数据。

第一个方面很容易。我们使用命名的互斥锁来防止主应用程序代码两次启动。该用户的所有正在运行的进程都可以看到已命名的互斥锁。

第二个方面要困难一点,但幸运是也不是很难。我们将使用.NET的命名管道功能来促进主应用程序(服务器)与后续启动(客户端)之间的通信。该用户的所有正在运行的进程也可以看到命名管道。

编码此混乱

我们使用的代码在这里给出,几乎是完整的。我只是在这里取消了using指令,以节省一些空间。

class Program
{        
    static string _AppName= Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().GetName().Name);
    static void Main(string[] args)
    {
        // we need to get our app name so that we can create unique names for our mutex and our pipe
            
        var notAlreadyRunning = true;
        // wrap the meat of the application code with a named mutex so it runs only once
        using (var mutex = new Mutex(true, _AppName + "Singleton", out notAlreadyRunning))
        {
            if (notAlreadyRunning)
            {
                // do additional work here, startup stuff
                Console.WriteLine("Running. Press any key to exit...");
                // ...
                // now process our initial main command line
                _ProcessCommandLine(args);
                // start the IPC sink.
                var srv = new NamedPipeServerStream(_AppName+"IPC", PipeDirection.InOut,1,PipeTransmissionMode.Message,PipeOptions.Asynchronous);
                // it's easier to use the AsyncCallback than it is to use Tasks here:
                // this can't block, so some form of async is a must

                srv.BeginWaitForConnection(new AsyncCallback(_ConnectionHandler), srv);

                // block here until exit
                Console.ReadKey();
                // if this was a windows forms app you would put your "Applicantion.Run(new MyForm());" here
                // finally, run any teardown code and exit

                srv.Close();
            }
            else // another instance is running
            {
                // connect to the main app
                var cli = new NamedPipeClientStream(".",_AppName + "IPC",PipeDirection.InOut);
                cli.Connect();
                var bf = new BinaryFormatter();
                // serialize and send the command line
                bf.Serialize(cli, args);
                cli.Close();
                // and exit
            }
        }
    }
    static void _ConnectionHandler(IAsyncResult result)
    {
        var srv = result.AsyncState as NamedPipeServerStream;
        srv.EndWaitForConnection(result);
        // we're connected, now deserialize the incoming command line
        var bf = new BinaryFormatter();
        var inargs = bf.Deserialize(srv) as string[];

        // process incoming command line
        _ProcessCommandLine(inargs);
        srv.Close();
        srv = new NamedPipeServerStream(_AppName + "IPC", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);

        srv.BeginWaitForConnection(new AsyncCallback(_ConnectionHandler), srv);
    }
    static void _ProcessCommandLine(string[] args)
    {
        // we received some command line
        // arguments.
        // do actual work here
        Console.Write("Command line recieved: ");
        for(var i = 0;i            
关注
打赏
1665926880
查看更多评论
0.1259s