次の方法で共有


リモート処理の例 : 非同期リモート処理

リモート処理のシナリオでの非同期プログラミングのサンプル アプリケーションを次に示します。この例では、最初にリモート オブジェクトに対する同期デリゲートを作成し、応答を待機するスレッドを説明するためにこれを呼び出します。次に非同期デリゲートと ManualResetEvent オブジェクトを使用してリモート オブジェクトのメソッドを呼び出し、応答を待機します。

このアプリケーションは、1 台のコンピュータ上で、またはネットワーク経由で実行されます。このアプリケーションをネットワーク経由で実行するには、クライアント構成の "localhost" をリモート コンピュータの名前で置き換える必要があります。

注意

.NET Framework リモート処理では、既定では認証または暗号化を行いません。したがって、クライアントやサーバーとリモートで対話する前に、ID の確認に必要な手順をすべて実行することをお勧めします。.NET Framework リモート処理アプリケーションの実行には、FullTrust アクセス許可が必要です。そのため、承認されていないクライアントがサーバー上でのアクセスを許可された場合は、完全な信頼を与えられているものとして、コードを実行できてしまいます。インターネット インフォメーション サービス (IIS : Internet Information Services) でリモート型をホストするか、リモート型をホストするためのカスタム チャネル シンク ペアを構築することによって、常にエンドポイントを認証し、通信ストリームを暗号化してください。

このサンプルをコンパイルするには

  1. コマンド プロンプトで次のコマンドを入力します。

    csc /t:library /out:ServiceClass.dll ServiceClass.cs

    vbc -r:ServiceClass.dll RemoteAsyncVB.vb

    csc /r:ServiceClass.dll Server.cs

    csc /r:ServiceClass.dll RemoteAsync.cs

  2. 同じディレクトリを指す 2 つのコマンド プロンプトを開きます。一方のコマンド プロンプトでは、「server」と入力します。もう一方のコマンド プロンプトでは、「RemoteAsyncVB」または「RemoteAsync」と入力します。

RemoteAsyncVB.vb

Imports System
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Messaging
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class RemotingDelegates
   
   
   Public Shared e As ManualResetEvent
   
   ' Declares two delegates, each of which represents 
   ' a function that returns a string. The names are strictly 
   ' for clarity in the code – there is no difference between
   ' the two delegates. (In fact, the same delegate type 
   ' could be used for both synchronous and asynchronous 
   ' calls.)
   Delegate Function RemoteSyncDelegate() As String
   Delegate Function RemoteAsyncDelegate() As String
   
   <MTAThread()> _
   Public Shared Sub Main()
      
      e = New ManualResetEvent(False)
      
      Console.WriteLine("Remote synchronous and asynchronous delegates.")
      Console.WriteLine(New [String]("-"c, 80))
      Console.WriteLine()
      
      ' Configuration is required in a remoting scenario, for both
      ' synchronous and asynchronous programming. You can use either
      ' a configuration file, as shown here, or method calls.
      RemotingConfiguration.Configure("SyncAsync.exe.config")
      
      ' The remaining steps are identical to single-
      ' AppDomain programming. First, create the service class. In this 
      ' case, the object is actually created on the server, and only a 
      ' single instance is created. (See the server configuration file, 
      ' ServerVB.exe.config.)
      Dim obj As New ServiceClass()
      
      If RemotingServices.IsTransparentProxy(obj) Then
         Console.WriteLine("It's remote.")
      Else
         Console.WriteLine("Uh-oh. It's local.")
         Return
      End If
      
      ' This delegate is a remote synchronous delegate.
      Dim RemoteSyncDel As New RemoteSyncDelegate(AddressOf obj.VoidCall)

      ' When invoked, program execution waits until the method returns.
      ' The return value is displayed to the console.
      Console.WriteLine(RemoteSyncDel())

      
      ' Next, the remote asynchronous call.
      ' First, create an AsyncCallback delegate that represents 
      ' the method to be executed when the asynchronous method has finished 
      ' executing.
      Dim RemoteCallback As New AsyncCallback(AddressOf RemotingDelegates.OurRemoteAsyncCallBack)
      
      ' Second, create the delegate to the method to 
      ' executed asynchronously.
      Dim RemoteDel As New RemoteAsyncDelegate(AddressOf obj.TimeConsumingRemoteCall)
      
      ' Finally, begin the method invocation.
      ' Note that execution on this thread continues immediately without 
      ' waiting for the return of the method call.
      Dim RemAr As IAsyncResult = RemoteDel.BeginInvoke(RemoteCallback, Nothing)
      ' If you want to block on the return:
      '      RemAr.AsyncWaitHandle.WaitOne();
      '      RemoteCallback(RemAr);

      ' Provide some feedback to indicate continued processing prior to 
      ' the return of the asynchronous call.
      Dim count As Integer = 0
      While Not RemAr.IsCompleted
         Console.Write("Not completed -- " & count & vbCr)
         count += 1
         ' The callback is made on a low priority worker thread. Blocking 
         ' the foreground thread for a millisecond each time enables the
         ' callback to execute. 
         Thread.Sleep(New TimeSpan(TimeSpan.TicksPerMillisecond))
      End While
      Console.WriteLine(vbCrLf & "Completed.")

   End Sub 'Main
    
   
   ' This is the method that the server calls when asynchronous 
   ' execution is complete. The method is represented by an AsyncCallBack 
   ' delegate, which determines its signature.
   Public Shared Sub OurRemoteAsyncCallBack(ByVal iar As IAsyncResult)
      ' The following nested cast looks confusing, because of the nature 
      ' of the Visual Basic casting operator, CType. Note that you could 
      ' get the same result with two separate casts:
      '    Dim ar As AsyncResult = CType(iar, AsyncResult)
      '    Dim del As RemoteAsyncDelegate = CType(ar.AsyncDelegate, RemoteAsyncDelegate)
      ' The first line casts the interface to an AsyncResult object to 
      ' access the AsyncDelegate property (in the second 
      ' line). This property returns a reference to the original delegate, 
      ' which must be cast back to its own type.
      Dim del As RemoteAsyncDelegate = CType(CType(iar, AsyncResult).AsyncDelegate, RemoteAsyncDelegate)
      Console.WriteLine(vbCrLf & "Result of the remote AsyncCallBack: " & del.EndInvoke(iar))
      Return
   End Sub 'OurRemoteAsyncCallBack
    
End Class 'RemotingDelegates

RemoteAsync.cs

using System;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Threading;

public class RemotingDelegates : MarshalByRefObject{


    public static ManualResetEvent e;

    public delegate string RemoteSyncDelegate();
    public delegate string RemoteAsyncDelegate();

    // This is the call that the AsyncCallBack delegate references.
    [OneWayAttribute]
   public void OurRemoteAsyncCallBack(IAsyncResult ar){
      RemoteAsyncDelegate del = (RemoteAsyncDelegate)((AsyncResult)ar).AsyncDelegate;
      Console.WriteLine("\r\n**SUCCESS**: Result of the remote AsyncCallBack: "  + del.EndInvoke(ar) );
      
        // Signal the thread.
        e.Set();
        return;
   }

    public static void Main(string[] Args){

        // IMPORTANT: .NET Framework remoting does not remote
        // static members. This class must be an instance before
        // the callback from the asynchronous invocation can reach this client.
        RemotingDelegates HandlerInstance = new RemotingDelegates();
        HandlerInstance.Run();        
 
    }

    public void Run(){
        // Enable this and the e.WaitOne call at the bottom if you 
        // are going to make more than one asynchronous call.
        e = new ManualResetEvent(false);

        Console.WriteLine("Remote synchronous and asynchronous delegates.");
        Console.WriteLine(new String('-',80));
        Console.WriteLine();

        // This is the only thing you must do in a remoting scenario
        // for either synchronous or asynchronous programming 
        // configuration.
        RemotingConfiguration.Configure("SyncAsync.exe.config");

        // The remaining steps are identical to single-
        // AppDomain programming.
        ServiceClass obj = new ServiceClass();
        
        // This delegate is a remote synchronous delegate.
        RemoteSyncDelegate Remotesyncdel = new RemoteSyncDelegate(obj.VoidCall);
        
        // When invoked, program execution waits until the method returns.
        // This delegate can be passed to another application domain
        // to be used as a callback to the obj.VoidCall method.
        Console.WriteLine(Remotesyncdel());

        // This delegate is an asynchronous delegate. Two delegates must 
        // be created. The first is the system-defined AsyncCallback 
        // delegate, which references the method that the remote type calls 
        // back when the remote method is done.

        AsyncCallback RemoteCallback = new AsyncCallback(this.OurRemoteAsyncCallBack);

        // Create the delegate to the remote method you want to use 
        // asynchronously.
        RemoteAsyncDelegate RemoteDel = new RemoteAsyncDelegate(obj.TimeConsumingRemoteCall);
        
        // Start the method call. Note that execution on this 
        // thread continues immediately without waiting for the return of 
        // the method call. 
        IAsyncResult RemAr = RemoteDel.BeginInvoke(RemoteCallback, null);

        // If you want to stop execution on this thread to 
        // wait for the return from this specific call, retrieve the 
        // IAsyncResult returned from the BeginIvoke call, obtain its 
        // WaitHandle, and pause the thread, such as the next line:
        // RemAr.AsyncWaitHandle.WaitOne();

        // To wait in general, if, for example, many asynchronous calls 
        // have been made and you want notification of any of them, or, 
        // like this example, because the application domain can be 
        // recycled before the callback can print the result to the 
        // console.
        //e.WaitOne();

   // This simulates some other work going on in this thread while the 
   // async call has not returned. 
   int count = 0;
   while(!RemAr.IsCompleted){
      Console.Write("\rNot completed: " + (++count).ToString());
      // Make sure the callback thread can invoke callback.
      Thread.Sleep(1);
   }
    }
}

Server.cs

using System;
using System.Runtime.Remoting;

public class Server{

   public static void Main(){
      RemotingConfiguration.Configure("server.exe.config");
      Console.WriteLine("Waiting...");
      Console.ReadLine();
   }
}

ServiceClass.cs

using System;
using System.Runtime.Remoting;

public class ServiceClass : MarshalByRefObject{

   public ServiceClass() {
      Console.WriteLine("ServiceClass created.");
   }

   public string VoidCall(){
      Console.WriteLine("VoidCall called.");
      return "You are calling the void call on the ServiceClass.";
   }

   public int GetServiceCode(){
      return this.GetHashCode();
   }

   public string TimeConsumingRemoteCall(){
      Console.WriteLine("TimeConsumingRemoteCall called.");
   
      for(int i = 0; i < 20000; i++){
         Console.Write("Counting: " + i.ToString());
         Console.Write("\r");
      }
      return "This is a time-consuming call.";
   }
}

Server.exe.config

<configuration>
   <system.runtime.remoting>
      <application>
         <service>
            <wellknown 
               type="ServiceClass, ServiceClass"
               mode="Singleton"
               objectUri="ServiceClass.rem"
            />
         </service>
         <channels>
            <channel 
               ref="http" 
               port="8080"
            />
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

SyncAsync.exe.config

<configuration>
   <system.runtime.remoting>
      <application>
         <client>
            <wellknown 
               type="ServiceClass, ServiceClass"
               url="https://localhost:8080/ServiceClass.rem"
            />
         </client>
         <channels>
            <channel 
               ref="http" 
               port="0"
            />
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

参照

概念

非同期リモート処理

その他の技術情報

リモート処理の例