リモート処理の例 : CallContext
このサンプルでは、CallContext クラスおよび ILogicalThreadAffinative インターフェイスを使用して、アプリケーション ドメインの境界またはコンテキストの境界を越える呼び出しの両端のスレッド間でデータを受け渡しします。
このアプリケーションは、1 台のコンピュータ上で、またはネットワーク経由で実行されます。このアプリケーションをネットワーク経由で実行するには、クライアント構成の "localhost" をリモート コンピュータの名前で置き換える必要があります。
このサンプルでは ServiceClass.vb はコンパイルされませんが、ILogicalThreadAffinative の例を示すためにこのサンプルに含まれています。
注意
.NET リモート処理では、既定では認証または暗号化を行いません。したがって、クライアントやサーバーとリモートで対話する前に、ID の確認に必要な手順をすべて実行することをお勧めします。.NET リモート処理アプリケーションの実行には、FullTrust アクセス許可が必要です。そのため、承認されていないクライアントがサーバー上でのアクセスを許可された場合は、完全な信頼を与えられているものとして、にコードを実行できてしまいます。インターネット インフォメーション サービス (IIS : Internet Information Services) でリモート型をホストするか、リモート型をホストするためのカスタム チャネル シンク ペアを構築することによって、常にエンドポイントを認証し、通信ストリームを暗号化してください。
このサンプルをコンパイルするには
コマンド プロンプトで次のコマンドを入力します。
csc /r:System.Runtime.Remoting.dll /t:library ServiceClass.cs
csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll client.cs
vbc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll clientvb.vb
csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll server.cs
ServiceClass.cs
using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Channels;
public class ContextBoundType : ContextBoundObject{
private DateTime starttime;
public ContextBoundType(){
Console.WriteLine("A ContextBoundType instance has been created.");
starttime = DateTime.Now;
}
~ContextBoundType(){
Console.WriteLine("ContextBoundType being collected after " + (new TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() + " seconds.");
}
public DateTime GetServerTime(){
Console.WriteLine("Time requested by a client.");
// This call overwrites the client's
// CallContextString.
CallContext.SetData("ServerThreadData", new CallContextString("This is the server side replacement."));
return DateTime.Now;
}
}
// One method of communicating between client and server is
// to use the CallContext. Calling CallContext essentially puts the data
// in a Thread Local Store. This means that the information is available
// to that thread or that "logical" thread (across application domains) only.
[Serializable]
public class CallContextString : ILogicalThreadAffinative{
String _str ="";
public CallContextString(String str){
_str = str;
Console.WriteLine("CallContextString created.");
}
public override String ToString(){
return _str;
}
}
ServiceClass.vb
このファイルは、説明のためだけに示されています。
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Messaging
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Channels
Public Class ContextBoundType
Inherits ContextBoundObject
Private StartTime As DateTime
Public Sub New()
Console.WriteLine("A ContextBoundType instance has been created. (Constructor)")
StartTime = DateTime.Now
End Sub 'New
Protected Overrides Sub Finalize()
Console.WriteLine("ContextBoundType being collected after " & (New TimeSpan(DateTime.Now.Ticks - starttime.Ticks)).ToString() & " seconds.")
MyBase.Finalize()
End Sub 'Finalize
Public Function GetServerTime() As DateTime
Console.WriteLine("Time requested by a client.")
' This call overwrites the client's
' CallContextString.
CallContext.SetData("ServerThreadData", New CallContextString("This is the server side replacement."))
Return DateTime.Now
End Function 'GetServerTime
End Class 'ContextBoundType
' One of the methods of communicating between client and server is
' to use the CallContext. Calling CallContext essentially puts the data
' in a Thread Local Store. This means that the information is available
' to that thread or that "logical" thread (across application domains) only.
<Serializable> _
Public Class CallContextString
Implements ILogicalThreadAffinative
Private _str As String = ""
Public Sub New(ByVal Contents As String)
_str = Contents
Console.WriteLine("CallContextString created with string ""{0}""", Contents)
End Sub 'New
Public Overrides Function ToString() As String
Return _str
End Function 'ToString
End Class 'CallContextString
ClientVB.vb
Imports System
Imports System.Reflection
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting.Contexts
Imports System.Runtime.Remoting.Messaging
Public Class ClientProcess
<MTAThread()> _
Public Shared Sub Main()
Dim Channel As New HttpChannel()
ChannelServices.RegisterChannel(Channel)
Dim RemoteType As New WellKnownClientTypeEntry(GetType(ContextBoundType), "https://localhost:8080/TcpCBOService")
RemotingConfiguration.RegisterWellKnownClientType(RemoteType)
' This sets a CallContextDataSlot on this thread. CallContextString
' will convert the ThreadLocalDataStore into a property on the
' message, which will then be merged into the ThreadLocalDataStore
' on the server. This is a nice way to pass information from client
' to server threads and back again. NOTE: This data store has
' logical thread scope. If an application domain has more than one
' thread making calls, each thread will have its own logical
' CallContext, and the server thread will keep each separate.
CallContext.SetData("ServerThreadData", New CallContextString("This is the thread data inserted on the client thread."))
Console.WriteLine("CallContextString prior to the call: " & CallContext.GetData("ServerThreadData").ToString())
Dim service As New ContextBoundType()
Console.WriteLine("Server time is: " & service.GetServerTime().ToLongTimeString())
Console.WriteLine("CallContextString after the call: " & CallContext.GetData("ServerThreadData").ToString())
End Sub 'Main
End Class 'ClientProcess
Client.cs
using System;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
public class ClientProcess{
public static void Main(string[] Args){
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel);
WellKnownClientTypeEntry remotetype = new WellKnownClientTypeEntry(typeof(ContextBoundType),"https://localhost:8080/TcpCBOService");
RemotingConfiguration.RegisterWellKnownClientType(remotetype);
// This sets a CallContextDataSlot on this thread.
// CallContextString will convert the ThreadLocalDataStore into
// a property on the message, which will then be merged into the
// ThreadLocalDataStore on the server. This is a nice way to pass
// information from client to server threads and back again.
// NOTE: This data store has logical thread scope. If an
// application domain has more than one thread making calls,
// each thread will have its own logical CallContext, and the
// server thread will keep each separate.
CallContext.SetData("ServerThreadData", new CallContextString("This is the thread data inserted on the client thread."));
Console.WriteLine("CallContextString prior to the call: " + CallContext.GetData("ServerThreadData").ToString());
ContextBoundType service = new ContextBoundType();
Console.WriteLine("Server time is: " + service.GetServerTime().ToLongTimeString());
Console.WriteLine("CallContextString after the call: " + CallContext.GetData("ServerThreadData").ToString());
}
}
Server.cs
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using System.Threading;
public class ServerProcess{
public static void Main(string[] Args){
HttpChannel channel = new HttpChannel(8080);
ChannelServices.RegisterChannel(channel);
WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(typeof(ContextBoundType),"TcpCBOService", WellKnownObjectMode.SingleCall);
RemotingConfiguration.RegisterWellKnownServiceType(WKSTE);
Console.WriteLine("Press enter to stop this process.");
Console.ReadLine();
}
}
参照
関連項目
CallContext
ILogicalThreadAffinative