C# .NET wcf调用方法冻结
我对WCF服务方法调用有一个问题,如果在同一进程上完成连接,该调用会冻结并且不会返回响应 以下是完整的代码(非常简化,仅显示所需内容): 连接已完成,但当调用“IsServiceInitiated”方法时,应用程序将冻结 但是,如果创建一个专用于启动服务器的应用程序,以及另一个专用于连接到服务器的客户机的应用程序,则该方法不会冻结并返回true 真的需要任何帮助 非常感谢 编辑:C# .NET wcf调用方法冻结,c#,.net,wcf,C#,.net,Wcf,我对WCF服务方法调用有一个问题,如果在同一进程上完成连接,该调用会冻结并且不会返回响应 以下是完整的代码(非常简化,仅显示所需内容): 连接已完成,但当调用“IsServiceInitiated”方法时,应用程序将冻结 但是,如果创建一个专用于启动服务器的应用程序,以及另一个专用于连接到服务器的客户机的应用程序,则该方法不会冻结并返回true 真的需要任何帮助 非常感谢 编辑: 好的,我添加了消息检查器和分派检查器,并在控制台中输出BeforeSendRequest和AfterReceiveR
好的,我添加了消息检查器和分派检查器,并在控制台中输出BeforeSendRequest和AfterReceiveRequest的结果。结果如下:
Before send request: Action = http://tempuri.org/IBaseService/IsServiceInitiated Reply =
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IBaseService/IsServiceInitiated</a:Action>
<a:MessageID>urn:uuid:d14b0af4-81c3-46c7-9b38-83a8fb092028</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPoy1+4Je4rwBHkZsB8NCWGqQAAAAAAM8Ng9k570ayit0OK365Vn8yY2g0amdHlrkBcRNGylUACQAA</VsDebuggerCausalityData>
</s:Header>
<s:Body>
<IsServiceInitiated xmlns="http://tempuri.org/" />
</s:Body>
</s:Envelope>
After receive request: Action = http://tempuri.org/IBaseService/IsServiceInitiated Reply =
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IBaseService/IsServiceInitiated</a:Action>
<a:MessageID>urn:uuid:d14b0af4-81c3-46c7-9b38-83a8fb092028</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPoy1+4Je4rwBHkZsB8NCWGqQAAAAAAM8Ng9k570ayit0OK365Vn8yY2g0amdHlrkBcRNGylUACQAA</VsDebuggerCausalityData>
<a:To s:mustUnderstand="1">net.tcp://localhost:7780/CustomService</a:To>
</s:Header>
<s:Body>
<IsServiceInitiated xmlns="http://tempuri.org/">
</IsServiceInitiated>
</s:Body>
</s:Envelope>
发送请求之前的:操作=http://tempuri.org/IBaseService/IsServiceInitiated 答复=
http://tempuri.org/IBaseService/IsServiceInitiated
urn:uuid:d14b0af4-81c3-46c7-9b38-83a8fb092028
http://www.w3.org/2005/08/addressing/anonymous
uIDPoy1+4JE4RWBHKZSB8NCWGQQAAAAAAAM8NG9K570AYIT0OK365VN8YY2G0AMDHLRKBCRNGYLUACQAA
接收请求后:操作=http://tempuri.org/IBaseService/IsServiceInitiated 答复=
http://tempuri.org/IBaseService/IsServiceInitiated
urn:uuid:d14b0af4-81c3-46c7-9b38-83a8fb092028
http://www.w3.org/2005/08/addressing/anonymous
uIDPoy1+4JE4RWBHKZSB8NCWGQQAAAAAAAM8NG9K570AYIT0OK365VN8YY2G0AMDHLRKBCRNGYLUACQAA
净。tcp://localhost:7780/CustomService
我等待冻结的方法,最后得到一个通信异常:
服务器没有提供有意义的回复;这可能是由于契约不匹配、会话过早关闭或内部服务器错误造成的
新编辑:
太棒了!!!
当使用单独的应用程序启动服务器和第一个应用程序将客户端连接到此服务器时,它会工作,消息检查器不会启动AfterReceiveRequest事件,但我会得到BeforeReceivePly输出:
Before receive reply: Action = http://tempuri.org/IBaseService/IsServiceInitiatedResponse Reply =
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IBaseService/IsServiceInitiatedResponse</a:Action>
<a:RelatesTo>urn:uuid:bc055419-68d6-4f08-8170-0d1097e11d39</a:RelatesTo>
<a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body>
<IsServiceInitiatedResponse xmlns="http://tempuri.org/">
<IsServiceInitiatedResult>true</IsServiceInitiatedResult>
</IsServiceInitiatedResponse>
</s:Body>
</s:Envelope>
收到回复之前:操作=http://tempuri.org/IBaseService/IsServiceInitiatedResponse 答复=
http://tempuri.org/IBaseService/IsServiceInitiatedResponse
urn:uuid:bc055419-68d6-4f08-8170-0d1097e11d39
http://www.w3.org/2005/08/addressing/anonymous
真的
再次编辑:
我注意到,如果在显示Windows窗体之前打开服务器主机(“Show”方法),则我的服务工作正常,但如果在显示任何Windows窗体之后或在Windows窗体的构造函数中打开主机,则WCF方法调用freeze。。。。。。。非常奇怪…您的代码似乎有几个问题。绑定设置有问题,服务定义和接口有问题,等等 以下是基于您的代码的工作副本。确保正确调整绑定 如果这不能解决您的问题,请粘贴客户端调用堆栈好吗
using System;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
CustomServer server = new CustomServer();
server.Open();
CustomClient client = new CustomClient();
client.Connect();
Console.WriteLine("Press Enter");
Console.ReadLine();
server.Close();
}
}
[ServiceContract(CallbackContract = typeof(IBaseServiceCallback))]
public interface IBaseService
{
[OperationContract]
bool IsServiceInitiated();
}
public interface IBaseServiceCallback
{
[OperationContract]
void TheCallback(string str);
}
//Change3
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, AutomaticSessionShutdown = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
[CallbackBehavior]
public class BaseServiceCallback : IBaseServiceCallback
{
public void TheCallback(string str)
{
Console.WriteLine(str);
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, AutomaticSessionShutdown = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class BaseService : IBaseService
{
public bool IsServiceInitiated()
{
return true;
}
}
public class CustomServer
{
private BaseService service;
private ServiceHost host;
public bool IsStarted
{
get { return host != null && host.State == CommunicationState.Opened; }
}
public CustomServer()
{
service = new BaseService();
host = new ServiceHost(service, new Uri[] { new Uri("net.tcp://localhost:7780") });
Type interfaceType = typeof(IBaseService);
// Create service end point
ServiceEndpoint endpointPipe = host.AddServiceEndpoint(interfaceType, new NetTcpBinding(), "CustomService");
// Define TCP binding
NetTcpBinding bindingPipe = (NetTcpBinding)endpointPipe.Binding;
//Change1
//bindingPipe.MaxReceivedMessageSize = long.MaxValue;
//bindingPipe.MaxBufferPoolSize = long.MaxValue;
//bindingPipe.MaxBufferSize = int.MaxValue;
//bindingPipe.ReaderQuotas.MaxDepth = 2048;
//bindingPipe.Security.Mode = SecurityMode.None;
//bindingPipe.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
//bindingPipe.Security.Message.ClientCredentialType = MessageCredentialType.None;
// Increase MaxItemsInObjectGraph for all operations behaviors
foreach (OperationDescription op in endpointPipe.Contract.Operations)
{
var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
}
// In order to publish the service contract, it is important to publish the metadata
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior();
}
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Add MEX endpoint
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:7780/IDMmex");
}
public void Open()
{
if (host != null)
{
host.Open();
}
}
public void Close()
{
if (host != null)
{
host.Close();
}
}
}
public class CustomClient
{
private IBaseService serviceProxy;
private BaseServiceCallback callback;
public CustomClient()
{
callback = new BaseServiceCallback();
}
public void Connect()
{
string serviceUrl = "net.tcp://localhost:7780/CustomService";
// Create a channel in order to find the exact call back type.
DuplexChannelFactory<IBaseService> sampleChannel = new DuplexChannelFactory<IBaseService>(callback, new NetTcpBinding(), new EndpointAddress(serviceUrl));
Type duplexChannelFactory = typeof(DuplexChannelFactory<>).MakeGenericType(new Type[] { typeof(IBaseService) });
object pipeFactory = Activator.CreateInstance(duplexChannelFactory, new object[] { callback, new NetTcpBinding(), new EndpointAddress(serviceUrl) });
// Get the service end point
ServiceEndpoint endpoint = (ServiceEndpoint)duplexChannelFactory.GetProperty("Endpoint").GetValue(pipeFactory, null);
// Configure TCP binding
//NetTcpBinding tcpBinding = (NetTcpBinding)endpoint.Binding;
//tcpBinding.MaxReceivedMessageSize = long.MaxValue;
//tcpBinding.MaxBufferPoolSize = long.MaxValue;
//tcpBinding.MaxBufferSize = int.MaxValue;
//tcpBinding.ReaderQuotas.MaxDepth = 2048;
//tcpBinding.Security.Mode = SecurityMode.None;
//tcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
//tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
//tcpBinding.SendTimeout = TimeSpan.MaxValue;
//tcpBinding.ReceiveTimeout = TimeSpan.MaxValue;
//tcpBinding.OpenTimeout = TimeSpan.MaxValue;
//tcpBinding.CloseTimeout = TimeSpan.MaxValue;
// Increase MaxItemsInObjectGraph for all operations behaviors
foreach (OperationDescription op in endpoint.Contract.Operations)
{
var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
}
//serviceProxy = sampleChannel.CreateChannel();
// Create the channel to retrieve the pipe proxy object
MethodInfo method = duplexChannelFactory.GetMethod("CreateChannel", new Type[0]);
object pipeProxyObject = method.Invoke(pipeFactory, new object[] { });
// Set the service proxy with the retrieved pipe proxy object
serviceProxy = (IBaseService)pipeProxyObject;
//Change2
((IChannel)serviceProxy).Open();
// FREEZE HERE...
bool isServerInitiated = serviceProxy.IsServiceInitiated();
}
}
}
使用系统;
运用系统反思;
使用System.ServiceModel;
使用System.ServiceModel.Channel;
使用System.ServiceModel.Description;
命名空间控制台应用程序5
{
班级计划
{
静态void Main(字符串[]参数)
{
CustomServer服务器=新的CustomServer();
server.Open();
CustomClient=新CustomClient();
client.Connect();
控制台。写入线(“按回车键”);
Console.ReadLine();
server.Close();
}
}
[ServiceContract(CallbackContract=typeof(IBaseServiceCallback))]
公共接口IBaseService
{
[经营合同]
bool是服务初始化的();
}
公共接口IBaseServiceCallback
{
[经营合同]
使回调无效(字符串str);
}
//变化3
//[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,IncludeExceptionDetailInFaults=true,AutomaticsSessionShutdown=false,ConcurrencyMode=ConcurrencyMode.Multiple)]
[CallbackBehavior]
公共类BaseServiceCallback:IBaseServiceCallback
{
公共作废回拨(字符串str)
{
控制台写入线(str);
}
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,IncludeExceptionDetailInFaults=true,AutomaticsSessionShutdown=false,ConcurrencyMode=ConcurrencyMode.Multiple)]
公共类BaseService:IBaseService
{
公共布尔值为服务初始化()
{
返回true;
}
}
公共类自定义服务器
{
专用基站服务;
专用服务主机;
公共图书馆开张了
{
获取{return host!=null&&host.State==CommunicationState.Opened;}
}
公共自定义服务器()
{
服务=新的BaseService();
主机=新服务主机(服务,新Uri[]){新Uri(“网络。tcp://localhost:7780") });
类型interfaceType=typeof(IBaseService);
//创建服务端点
ServiceEndpoint endpointPipe=host.AddServiceEndpoint(interfaceType,new NetTcpBinding(),“CustomService”);
//定义TCP绑定
NetTcpBinding bindingPipe=(NetTcpBinding)endpointPipe.Binding;
//变化1
//bindingPipe.MaxReceivedMessageSize=long.MaxValue;
//bindingPipe.MaxBufferPoolSize=long.MaxValue;
//bindingPipe.MaxBufferSize=int.MaxValue;
//bindingPipe.ReaderQuotas.MaxDepth=2048;
//bindingPipe.Security.Mode=SecurityMode.None;
//bindingPipe.Security.Transport.ClientCredentialType=TcpClientCredentialType.None;
//bindingPipe.Security.Message.ClientCredentialType=MessageCredentialType.None;
//为所有操作行为增加MaxItemsInObjectGraph
foreach(endpointPipe.Contract.Operations中的OperationDescription op)
Before receive reply: Action = http://tempuri.org/IBaseService/IsServiceInitiatedResponse Reply =
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IBaseService/IsServiceInitiatedResponse</a:Action>
<a:RelatesTo>urn:uuid:bc055419-68d6-4f08-8170-0d1097e11d39</a:RelatesTo>
<a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body>
<IsServiceInitiatedResponse xmlns="http://tempuri.org/">
<IsServiceInitiatedResult>true</IsServiceInitiatedResult>
</IsServiceInitiatedResponse>
</s:Body>
</s:Envelope>
using System;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
CustomServer server = new CustomServer();
server.Open();
CustomClient client = new CustomClient();
client.Connect();
Console.WriteLine("Press Enter");
Console.ReadLine();
server.Close();
}
}
[ServiceContract(CallbackContract = typeof(IBaseServiceCallback))]
public interface IBaseService
{
[OperationContract]
bool IsServiceInitiated();
}
public interface IBaseServiceCallback
{
[OperationContract]
void TheCallback(string str);
}
//Change3
//[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, AutomaticSessionShutdown = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
[CallbackBehavior]
public class BaseServiceCallback : IBaseServiceCallback
{
public void TheCallback(string str)
{
Console.WriteLine(str);
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults = true, AutomaticSessionShutdown = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class BaseService : IBaseService
{
public bool IsServiceInitiated()
{
return true;
}
}
public class CustomServer
{
private BaseService service;
private ServiceHost host;
public bool IsStarted
{
get { return host != null && host.State == CommunicationState.Opened; }
}
public CustomServer()
{
service = new BaseService();
host = new ServiceHost(service, new Uri[] { new Uri("net.tcp://localhost:7780") });
Type interfaceType = typeof(IBaseService);
// Create service end point
ServiceEndpoint endpointPipe = host.AddServiceEndpoint(interfaceType, new NetTcpBinding(), "CustomService");
// Define TCP binding
NetTcpBinding bindingPipe = (NetTcpBinding)endpointPipe.Binding;
//Change1
//bindingPipe.MaxReceivedMessageSize = long.MaxValue;
//bindingPipe.MaxBufferPoolSize = long.MaxValue;
//bindingPipe.MaxBufferSize = int.MaxValue;
//bindingPipe.ReaderQuotas.MaxDepth = 2048;
//bindingPipe.Security.Mode = SecurityMode.None;
//bindingPipe.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
//bindingPipe.Security.Message.ClientCredentialType = MessageCredentialType.None;
// Increase MaxItemsInObjectGraph for all operations behaviors
foreach (OperationDescription op in endpointPipe.Contract.Operations)
{
var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
}
// In order to publish the service contract, it is important to publish the metadata
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior();
}
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Add MEX endpoint
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:7780/IDMmex");
}
public void Open()
{
if (host != null)
{
host.Open();
}
}
public void Close()
{
if (host != null)
{
host.Close();
}
}
}
public class CustomClient
{
private IBaseService serviceProxy;
private BaseServiceCallback callback;
public CustomClient()
{
callback = new BaseServiceCallback();
}
public void Connect()
{
string serviceUrl = "net.tcp://localhost:7780/CustomService";
// Create a channel in order to find the exact call back type.
DuplexChannelFactory<IBaseService> sampleChannel = new DuplexChannelFactory<IBaseService>(callback, new NetTcpBinding(), new EndpointAddress(serviceUrl));
Type duplexChannelFactory = typeof(DuplexChannelFactory<>).MakeGenericType(new Type[] { typeof(IBaseService) });
object pipeFactory = Activator.CreateInstance(duplexChannelFactory, new object[] { callback, new NetTcpBinding(), new EndpointAddress(serviceUrl) });
// Get the service end point
ServiceEndpoint endpoint = (ServiceEndpoint)duplexChannelFactory.GetProperty("Endpoint").GetValue(pipeFactory, null);
// Configure TCP binding
//NetTcpBinding tcpBinding = (NetTcpBinding)endpoint.Binding;
//tcpBinding.MaxReceivedMessageSize = long.MaxValue;
//tcpBinding.MaxBufferPoolSize = long.MaxValue;
//tcpBinding.MaxBufferSize = int.MaxValue;
//tcpBinding.ReaderQuotas.MaxDepth = 2048;
//tcpBinding.Security.Mode = SecurityMode.None;
//tcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
//tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
//tcpBinding.SendTimeout = TimeSpan.MaxValue;
//tcpBinding.ReceiveTimeout = TimeSpan.MaxValue;
//tcpBinding.OpenTimeout = TimeSpan.MaxValue;
//tcpBinding.CloseTimeout = TimeSpan.MaxValue;
// Increase MaxItemsInObjectGraph for all operations behaviors
foreach (OperationDescription op in endpoint.Contract.Operations)
{
var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
}
}
//serviceProxy = sampleChannel.CreateChannel();
// Create the channel to retrieve the pipe proxy object
MethodInfo method = duplexChannelFactory.GetMethod("CreateChannel", new Type[0]);
object pipeProxyObject = method.Invoke(pipeFactory, new object[] { });
// Set the service proxy with the retrieved pipe proxy object
serviceProxy = (IBaseService)pipeProxyObject;
//Change2
((IChannel)serviceProxy).Open();
// FREEZE HERE...
bool isServerInitiated = serviceProxy.IsServiceInitiated();
}
}
}
CustomClient customClient = new CustomClient();
CustomServer customServer = new CustomServer();
Exception serverStartException = null;
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
try
{
customServer.Start();
}
catch (Exception e)
{
serverStartException = e;
}
}
int maxTries = 5;
int currentTry = 0;
while (!customServer.IsStarted && currentTry < maxTries && serverStartException == null)
{
System.Threading.Thread.Sleep(1000);
currentTry++;
}
if (serverStartException != null)
{
throw new Exception("The server couldn't start", serverStartException );
}
else if (!customServer.IsStarted)
{
throw new Exception("The server couldn't start for unknown reason");
}
customClient.Connect();
if (customClient.ServiceProxy.IsServiceInitiated())
{
MessageBox.Show("Server initiated");
}
ServiceHost host = new ServiceHost(typeof(BaseService));
host.Open();
Application.Run(new BaseForm()); // already exists