views:

163

answers:

1

I ran into a remoting exception:

"This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server."

The cause is best explained by this blog entry I found:

The second case is more obscure. This occurs where the client makes a call to the server, the server returns an object reference, and the client then makes a call on the referenced object on the server. If the referenced object is in a secondary AppDomain on the server the above exception may be thrown. If the the problem occurs it is because channel registration only applies to the AppDomain in which RegisterChannel is called and no channel has been registered in the secondary AppDomain. The object reference returned to the client points to the object in the secondary AppDomain, not to its proxy in the primary AppDomain, and so there is no channel between the client and the secondary AppDomain across which the call can pass. Solution: register a channel in the secondary AppDomain in which the referenced object exists.

This does fit my scenario as I have a service that loads plugins into separate appdomains. Object instances (implementations of an interface defined in an assembly referenced by all assemblies) are created in the secondary appdomains and referenced by the service (cross-appdomain, so the service has proxy references). The service then returns these proxy references to an application. There are registered channels between the application and the service, but nothing between the plugin and the application.

I thought that a proxy would be enough to cross the appdomain boundaries. Do I really have to create channels between the plugins and the application? That doesn't seem right at all, so I must be missing something.

A: 

In order to use remoting across appdomains on objects derived from MarshalByRefObject it is necessary to create channels on both ends. Thus, you must create channels in each appdomain. There are efficient channels to do this locally on the same machine e.g. the IPC channel (uses named pipes).

If the communication is "one-way", in the sense that only one of the sides is calling methods on proxies, you register a client channel here, and the server channel on the side which creates the objects.

In case you need to go both ways, e.g. pass a logging object to the "server" in order to receive continuous log feedback, you must register a server channel at both ends, as the client suddenly also serves objects:

class MyLogger : MarshalByRefObject
{
    public Log(string text) { ... }
}

MyLogger logger = new MyLogger();
proxyObj.LongRunningCommand(logger);
Ron Cohen