[英]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(); }
我真的為此花費了很多時間,我將非常感謝每一個解決方案或想到如何更高級地調試它。
在帶有 UI 的應用程序中托管 wcf 服務有點棘手,所以我希望這會對某人有所幫助。
摘自《 Learning WCF:實踐指南》一書,Michele Leroux Bustamante,第 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();
}
}
這意味着消息是在線程池中的線程上處理的,而不是通過消息循環。
首先,當我們占用操作系統端口來托管服務時,我們應該給當前帳戶權限。
這個 function 可以通過以下命令完成。
Netsh http 添加 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();
}
有時,當服務合同沒有命名空間屬性時,它可能會遇到問題。
如果問題仍然存在,請隨時告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.