一种解决方案中从wpf客户端调用服务器期间出现超时异常
Timeout Exception during call from wpf client to server in one solution
问题是什么:System.TimeoutException:'请求通道在 00:00:59.977913 之后等待回复时超时。所以,基本上什么都可以。
我有什么:
我创建了一个简单的解决方案来找到修复方法。真正让我感到困惑的是控制台应用程序工作得很好,但是具有相同配置的 wpf 应用程序不起作用。解决方案包括四个项目(调试代码,请勿评判):
包含合同及其实施的图书馆。
public class DeviceService : IDeviceService
{
public string GetDevices()
{
return "hello world";
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
带主机的库。
public class DeviceServiceHostFactory
{
ServiceHost host;
public DeviceServiceHostFactory()
{
ServiceMetadataBehavior metadataBehavior;
BasicHttpBinding binding = new BasicHttpBinding();
Uri address = new Uri("http://localhost:4000/");
host = new ServiceHost(typeof(DeviceService), address);
Type contract = typeof(IDeviceService);
host.AddServiceEndpoint(contract, binding, "");
}
public void Start()
{
host.Open();
}
public void Stop()
{
host.Close();
}
}
启动服务并使用它的桌面应用程序(不工作)
public partial class MainWindow : Window
{
private DeviceServiceHostFactory _deviceService;
public MainWindow()
{
InitializeComponent();
try
{
_deviceService = new DeviceServiceHostFactory();
_deviceService.Start();
}
catch (Exception ex)
{
_deviceService.Stop();
Console.WriteLine(ex.StackTrace);
}
}
private void Btn_custom_Click(object sender, RoutedEventArgs e)
{
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint =
new EndpointAddress("http://localhost:4000/");
var factory =
new ChannelFactory<IDeviceService>(
binding, endpoint);
var channel = factory.CreateChannel();
txt_custom.Text = channel.GetDevices();
Console.WriteLine();
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
控制台应用程序(工作正常)
class Program
{
static void Main(string[] args)
{
DeviceServiceHostFactory _deviceService = new
DeviceServiceHostFactory();
try
{
_deviceService.Start();
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint =
new EndpointAddress("http://localhost:4000/");
var factory =
new ChannelFactory<IDeviceService>(
binding, endpoint);
var channel = factory.CreateChannel();
Console.WriteLine(channel.GetDevices());
Console.ReadLine();
}
catch (Exception ex)
{
_deviceService.Stop();
Console.WriteLine(ex.StackTrace);
}
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
我真的为此花了很多时间,我将非常感谢每一个解决方案或想到如何调试它更高级。
首先,我们在占用操作系统端口托管服务时,应该给当前账号权限。
这个功能可以通过下面的命令来完成。
Netsh http add urlacl url=https://+:80/MyUri user=DOMAIN\user
https://docs.microsoft.com/en-us/windows/win32/http/add-urlacl
如果我们不想这样做,我们可以直接 运行 使用管理员帐户的服务。
因此,我怀疑托管服务的过程有问题。您是否尝试过 运行使用管理员帐户运行 WPF 应用程序?
此外,我建议你在服务契约中添加一个命名空间。
[ServiceContract(Namespace ="MyNamespace")]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
有时,如果服务合同没有命名空间 属性,它可能 运行 会出现问题 属性。
如果问题仍然存在,请随时告诉我。
在 UI 的应用程序中托管 wcf 服务有点棘手,所以我希望这对某人有所帮助。
从书Learning WCF: A hands-On Guide By Michele Leroux Bustamante, Chapter 4,如需更多信息,请查找本书。
要在 Windows 应用程序或 WPF 应用程序中托管服务,我们必须创建一个新线程以在新的同步上下文中启动它。可以通过两种方式完成:
首先,是在创建UI线程之前创建服务主机。这里服务在应用程序启动之前在新的同步上下文中执行。
static class Program
{
static void Main()
{
DeviceServiceHostFactory deviceService = new DeviceServiceHostFactory();
deviceService.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow);
}
}
其次,在UI创建
之后,在单独的线程上初始化服务主机
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread thread;
thread = new Thread(ServiceInitialize);
thread.IsBackground = true;
thread.Start();
}
private void ServiceInitialize()
{
var service = new DeviceServiceHostFactory();
service.Start();
}
}
这意味着消息是在线程池中的线程上处理的,而不是通过消息循环。
问题是什么:System.TimeoutException:'请求通道在 00:00:59.977913 之后等待回复时超时。所以,基本上什么都可以。
我有什么:
我创建了一个简单的解决方案来找到修复方法。真正让我感到困惑的是控制台应用程序工作得很好,但是具有相同配置的 wpf 应用程序不起作用。解决方案包括四个项目(调试代码,请勿评判):
包含合同及其实施的图书馆。
public class DeviceService : IDeviceService { public string GetDevices() { return "hello world"; } } [ServiceContract] public interface IDeviceService { [OperationContract] string GetDevices(); }
带主机的库。
public class DeviceServiceHostFactory { ServiceHost host; public DeviceServiceHostFactory() { ServiceMetadataBehavior metadataBehavior; BasicHttpBinding binding = new BasicHttpBinding(); Uri address = new Uri("http://localhost:4000/"); host = new ServiceHost(typeof(DeviceService), address); Type contract = typeof(IDeviceService); host.AddServiceEndpoint(contract, binding, ""); } public void Start() { host.Open(); } public void Stop() { host.Close(); } }
启动服务并使用它的桌面应用程序(不工作)
public partial class MainWindow : Window { private DeviceServiceHostFactory _deviceService; public MainWindow() { InitializeComponent(); try { _deviceService = new DeviceServiceHostFactory(); _deviceService.Start(); } catch (Exception ex) { _deviceService.Stop(); Console.WriteLine(ex.StackTrace); } } private void Btn_custom_Click(object sender, RoutedEventArgs e) { BasicHttpBinding binding = new BasicHttpBinding(); EndpointAddress endpoint = new EndpointAddress("http://localhost:4000/"); var factory = new ChannelFactory<IDeviceService>( binding, endpoint); var channel = factory.CreateChannel(); txt_custom.Text = channel.GetDevices(); Console.WriteLine(); } } [ServiceContract] public interface IDeviceService { [OperationContract] string GetDevices(); }
控制台应用程序(工作正常)
class Program { static void Main(string[] args) { DeviceServiceHostFactory _deviceService = new DeviceServiceHostFactory(); try { _deviceService.Start(); BasicHttpBinding binding = new BasicHttpBinding(); EndpointAddress endpoint = new EndpointAddress("http://localhost:4000/"); var factory = new ChannelFactory<IDeviceService>( binding, endpoint); var channel = factory.CreateChannel(); Console.WriteLine(channel.GetDevices()); Console.ReadLine(); } catch (Exception ex) { _deviceService.Stop(); Console.WriteLine(ex.StackTrace); } } } [ServiceContract] public interface IDeviceService { [OperationContract] string GetDevices(); }
我真的为此花了很多时间,我将非常感谢每一个解决方案或想到如何调试它更高级。
首先,我们在占用操作系统端口托管服务时,应该给当前账号权限。
这个功能可以通过下面的命令来完成。
Netsh http add urlacl url=https://+:80/MyUri user=DOMAIN\user
https://docs.microsoft.com/en-us/windows/win32/http/add-urlacl
如果我们不想这样做,我们可以直接 运行 使用管理员帐户的服务。
因此,我怀疑托管服务的过程有问题。您是否尝试过 运行使用管理员帐户运行 WPF 应用程序?
此外,我建议你在服务契约中添加一个命名空间。
[ServiceContract(Namespace ="MyNamespace")]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
有时,如果服务合同没有命名空间 属性,它可能 运行 会出现问题 属性。
如果问题仍然存在,请随时告诉我。
在 UI 的应用程序中托管 wcf 服务有点棘手,所以我希望这对某人有所帮助。
从书Learning WCF: A hands-On Guide By Michele Leroux Bustamante, Chapter 4,如需更多信息,请查找本书。
要在 Windows 应用程序或 WPF 应用程序中托管服务,我们必须创建一个新线程以在新的同步上下文中启动它。可以通过两种方式完成:
首先,是在创建UI线程之前创建服务主机。这里服务在应用程序启动之前在新的同步上下文中执行。
static class Program
{
static void Main()
{
DeviceServiceHostFactory deviceService = new DeviceServiceHostFactory();
deviceService.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow);
}
}
其次,在UI创建
之后,在单独的线程上初始化服务主机 public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread thread;
thread = new Thread(ServiceInitialize);
thread.IsBackground = true;
thread.Start();
}
private void ServiceInitialize()
{
var service = new DeviceServiceHostFactory();
service.Start();
}
}
这意味着消息是在线程池中的线程上处理的,而不是通过消息循环。