私は奇妙な問題を抱えています。WCF ホストが元の AppDomain でホストされている場合、コードの実行には 1.25 秒かかります。ただし、新しい AppDomain に配置すると、まだ net.pipe または net.tcp を使用して通信しているにもかかわらず、プロセスの実行に 4.7 秒かかります。下部のコメントアウトされたブロックに app.config を含むコードを次に示します。
namespace ConsoleApplication2
{
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.ServiceModel;
using System.Threading.Tasks;
using Client;
internal class Program
{
#region Methods
private static void Main(string[] args)
{
var p = new Program();
p.Execute();
}
#endregion
public void Execute()
{
var hosts = Enumerable.Range(0, 1).Select(CreateNewHost).ToArray();
var r = new Random();
var cb = new ConcurrentDictionary<int, string>();
Action a = () =>
{
try
{
Parallel.For(
0,
10000,
i =>
{
//string ep = String.Format("net.pipe://localhost/iService{0}", hosts[r.Next(0, hosts.Length)]);
string ep = String.Format("net.tcp://localhost:{0}/iService", hosts[r.Next(0, hosts.Length)]);
string s=null;
//using (var cli = new ServiceClassClient("NetNamedPipeBinding_IServiceClass", ep))
using (var cli = new ServiceClassClient("NetTcpBinding_IServiceClass", ep))
{
s = cli.Ping();
}
if (!String.IsNullOrEmpty(s))
{
cb[i] = s;
}
});
}
catch (AggregateException aggregateException)
{
Console.WriteLine(aggregateException);
}
};
Console.WriteLine("\n\nIt took {0:G}", a.TimeThis());
Console.ReadKey();
}
static int CreateNewHost(int s)
{
//uncomment for in-process host
//var h1 = new Host();
//return h1.Port;
var appDomain = AppDomain.CreateDomain(
"A" + s,
null,
new AppDomainSetup
{
LoaderOptimization = LoaderOptimization.MultiDomain,
DisallowBindingRedirects = true
});
var assemblyName = Assembly.GetAssembly(typeof(Host)).FullName;
var h = appDomain.CreateInstanceAndUnwrap(assemblyName, typeof(Host).FullName) as Host;
return h.Port;
}
}
//comment out MarshalByRefObject for in-process host
public class Host:MarshalByRefObject
{
#region Fields
private readonly ServiceHost host;
private readonly int port;
#endregion
#region Constructors and Destructors
public Host()
{
this.port = this.GetFreePort();
var ub = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "net.tcp" };
var up = new UriBuilder { Host = "localhost", Scheme = "net.pipe", Path = "iService" + this.port };
this.host = new ServiceHost(typeof(ServiceClass), ub.Uri);
var netNamedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
this.host.AddServiceEndpoint(typeof(IServiceClass), netNamedPipeBinding, up.Uri);
var un = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "net.tcp", Path = "iService" };
var netTcpBinding = new NetTcpBinding(SecurityMode.None);
this.host.AddServiceEndpoint(typeof(IServiceClass), netTcpBinding, un.Uri);
//#if DEBUG
//var us = new UriBuilder { Host = "localhost", Port = this.port, Scheme = "http", Path = "iServiceMeta" };
//var smb = new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetUrl = us.Uri };
//this.host.Description.Behaviors.Add(smb);
//#endif
this.host.Open();
Console.WriteLine("Listening at {0}", this.host.BaseAddresses[0].AbsoluteUri);
}
#endregion
#region Public Properties
public int Port
{
get
{
return this.port;
}
}
public ServiceHost ServiceHost
{
get
{
return this.host;
}
}
#endregion
#region Methods
private int GetFreePort()
{
TcpConnectionInformation[] connections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections();
IPEndPoint[] listeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
var udps = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners();
var r = new Random();
int port;
do
{
port = r.Next(1025, 65534);
}
while (listeners.Any(a => a.Port == port) || connections.Any(a => a.LocalEndPoint.Port == port) || udps.Any(a=>a.Port==port));
return port;
}
#endregion
}
[ServiceContract]
internal interface IServiceClass
{
#region Public Methods and Operators
[OperationContract]
string Ping();
#endregion
}
internal class ServiceClass : IServiceClass
{
#region Public Methods and Operators
public string Ping()
{
return ((new Random()).NextDouble() * (new Random()).NextDouble()).ToString("F11");
}
#endregion
}
public static class Extensions
{
#region Public Methods and Operators
public static TimeSpan TimeThis(this Action action)
{
var sw = new Stopwatch();
sw.Start();
action.Invoke();
sw.Stop();
return sw.Elapsed;
}
#endregion
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18033
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Client
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IServiceClass")]
public interface IServiceClass
{
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IServiceClass/Ping", ReplyAction = "http://tempuri.org/IServiceClass/PingResponse")]
string Ping();
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IServiceClassChannel : IServiceClass, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ServiceClassClient : System.ServiceModel.ClientBase<IServiceClass>, IServiceClass
{
public ServiceClassClient()
{
}
public ServiceClassClient(string endpointConfigurationName)
: base(endpointConfigurationName)
{
}
public ServiceClassClient(string endpointConfigurationName, string remoteAddress)
: base(endpointConfigurationName, remoteAddress)
{
}
public ServiceClassClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
: base(endpointConfigurationName, remoteAddress)
{
}
public ServiceClassClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
: base(binding, remoteAddress)
{
}
public string Ping()
{
return base.Channel.Ping();
}
}
}
/*
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_IServiceClass">
<security mode="None" />
</binding>
</netNamedPipeBinding>
<netTcpBinding>
<binding name="NetTcpBinding_IServiceClass">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="" binding="netNamedPipeBinding"
bindingConfiguration="NetNamedPipeBinding_IServiceClass" contract="IServiceClass"
name="NetNamedPipeBinding_IServiceClass" />
<endpoint address="" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IServiceClass" contract="IServiceClass"
name="NetTcpBinding_IServiceClass" />
</client>
</system.serviceModel>
</configuration>
*/