web-dev-qa-db-ja.com

Windows名前付きパイプ(.Net)との非同期双方向通信

相互に通信する必要のあるWindowsサービスとGUIがあります。どちらもいつでもメッセージを送信できます。

NamedPipesの使用を検討していますが、ストリームの読み取りと書き込みを同時に行うことはできないようです(または、少なくともこのケースをカバーする例は見つかりません)。

単一の名前付きパイプを介してこの種の双方向通信を行うことは可能ですか?または、2つのパイプ(1つはGUI->サービスから、もう1つはサービス-> GUIから)を開く必要がありますか?

16
steve cook

WCFを使用すると、二重名前付きパイプを使用できます

// Create a contract that can be used as a callback
public interface IMyCallbackService
{
    [OperationContract(IsOneWay = true)]
    void NotifyClient();
}

// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
    [OperationContract]
    string ProcessData();
}

サービスを実装する

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
    public string ProcessData()
    {
        // Get a handle to the call back channel
        var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();

        callback.NotifyClient();
        return DateTime.Now.ToString();
    }
}

サービスをホストする

class Server
{
    static void Main(string[] args)
    {
        // Create a service Host with an named pipe endpoint
        using (var Host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
        {
            Host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
            Host.Open();

            Console.WriteLine("Simple Service Running...");
            Console.ReadLine();

            Host.Close();
        }
    }
}

クライアントアプリケーションを作成します。この例では、Clientクラスがコールバックコントラクトを実装しています。

class Client : IMyCallbackService
{
    static void Main(string[] args)
    {
        new Client().Run();
    }

    public void Run()
    {
        // Consume the service
        var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
        var proxy = factory.CreateChannel();

        Console.WriteLine(proxy.ProcessData());
    }

    public void NotifyClient()
    {
        Console.WriteLine("Notification from Server");
    }
}
27
Rohan West

単一のポイントを使用してメッセージ(この場合は単一のパイプ)を蓄積すると、メッセージの方向も自分で処理する必要があります(さらに、パイプにシステム全体のロックを使用する必要があります)。

したがって、反対方向の2本のパイプを使用します。

(別のオプションは、2つのMSMQキューを使用することです)。

2

名前付きパイプストリームクラス(サーバーまたはクライアント)は、InOutのPipeDirectionを使用して構築する必要があります。おそらくサービス内に1つのNamedPipeServerStreamが必要です。これは、任意の数のNamedPipeClientStreamオブジェクトで共有できます。パイプの名前と方向を使用してNamedPipeServerStreamを作成し、パイプの名前、サーバーの名前、およびPipeDirectionを使用してNamedPipeClientStreamを作成します。これで準備完了です。

2
Ben Brammer