C# WCF命名管道在WinApp中超时,但在ConsoleApp中不超时?
与之相关的,似乎是死的(线程):/ 我想知道为什么下面的代码在ConsoleApplications中可以完美地工作,但是当我对Windows应用程序执行完全相同的操作时,调用“Console.WriteLine(proxy.ProcessData());”时,客户端会超时。奇怪的是,服务器方法“ProcessData”在没有任何异常的情况下被调用,但在默认的1分钟后我仍然得到一个超时 我怎样才能解决这个问题。。。和ConsoleApp和WinApp之间的区别到底是什么(除了明显的区别之外),这就是为什么这样的东西不起作用的原因 使用WCF可以使用双工命名管道C# WCF命名管道在WinApp中超时,但在ConsoleApp中不超时?,c#,wcf,console-application,named-pipes,windows-applications,C#,Wcf,Console Application,Named Pipes,Windows Applications,与之相关的,似乎是死的(线程):/ 我想知道为什么下面的代码在ConsoleApplications中可以完美地工作,但是当我对Windows应用程序执行完全相同的操作时,调用“Console.WriteLine(proxy.ProcessData());”时,客户端会超时。奇怪的是,服务器方法“ProcessData”在没有任何异常的情况下被调用,但在默认的1分钟后我仍然得到一个超时 我怎样才能解决这个问题。。。和ConsoleApp和WinApp之间的区别到底是什么(除了明显的区别之外),这
// Create a contract that can be used as a callback
public interface IMyCallbackService
{
[OperationContract(IsOneWay = true)]
void NotifyClient();
}
// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
[OperationContract]
string ProcessData();
}
实施服务
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
public string ProcessData()
{
// Get a handle to the call back channel
var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();
callback.NotifyClient();
return DateTime.Now.ToString();
}
}
class Server
{
static void Main(string[] args)
{
// Create a service host with an named pipe endpoint
using (var host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
{
host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
host.Open();
Console.WriteLine("Simple Service Running...");
Console.ReadLine();
host.Close();
}
}
}
创建客户机应用程序,在本例中,客户机类实现回调契约
class Client : IMyCallbackService
{
static void Main(string[] args)
{
new Client().Run();
}
public void Run()
{
// Consume the service
var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.ProcessData());
}
public void NotifyClient()
{
Console.WriteLine("Notification from Server");
}
}
类客户端:IMyCallbackService
{
静态void Main(字符串[]参数)
{
新客户端().Run();
}
公开募捐
{
//消费服务
var factory=new DuplexChannelFactory(new InstanceContext(this))、new NetNamedPipeBinding()、new EndpointAddress(“net”)。pipe://localhost/SimpleService"));
var proxy=factory.CreateChannel();
Console.WriteLine(proxy.ProcessData());
}
public void NotifyClient()
{
Console.WriteLine(“来自服务器的通知”);
}
}
原因是调用回调时,同步上下文非常重要。
您可以从内部ProcessData
调用回调方法
对于控制台应用程序,没有任何同步上下文集,这意味着当ProcessData
返回时,当主线程等待时,WCF将在单独的线程中调用客户端上的回调方法。如果在控制台消息中记录线程ID,则可以看到这一点
对于Windows应用程序,主线程设置同步上下文(WinForms或WPF)。如果您从主线程调用服务,那么WCF将尝试在相同的同步上下文中调用您的回调方法。但是此同步上下文的唯一线程正忙于等待ProcessData
返回
您可以通过两种方式解决此问题:
1.为回调设置UseSynchronizationContext=false
。
2.从应用程序的后台线程调用您的服务-然后将在其他线程池线程上调用回调
请注意,使用这两个选项,您无法直接从这些后台线程访问UI元素-您需要封送对UI线程的调用。原因是调用回调时,同步上下文非常重要。 您可以从内部
ProcessData
调用回调方法
对于控制台应用程序,没有任何同步上下文集,这意味着当ProcessData
返回时,当主线程等待时,WCF将在单独的线程中调用客户端上的回调方法。如果在控制台消息中记录线程ID,则可以看到这一点
对于Windows应用程序,主线程设置同步上下文(WinForms或WPF)。如果您从主线程调用服务,那么WCF将尝试在相同的同步上下文中调用您的回调方法。但是此同步上下文的唯一线程正忙于等待ProcessData
返回
您可以通过两种方式解决此问题:
1.为回调设置UseSynchronizationContext=false
。
2.从应用程序的后台线程调用您的服务-然后将在其他线程池线程上调用回调
请注意,使用这两个选项,您无法直接从这些后台线程访问UI元素-您需要封送对UI线程的调用