簡體   English   中英

在一個解決方案中從 wpf 客戶端到服務器的調用期間出現超時異常

[英]Timeout Exception during call from wpf client to server in one solution

問題是什么: System.TimeoutException: '請求通道在 00:00:59.977913 之后等待回復時超時。 所以,基本上它可以是一切。

我有什么:

我創建了一個簡單的解決方案來解決問題。 真正讓我困惑的是控制台應用程序工作得很好,但是具有相同配置的 wpf 應用程序不起作用。 解決方案包括四個項目(出於調試目的編寫的代碼,請不要判斷它):

  1. 帶有合同及其實施的圖書館。

     public class DeviceService: IDeviceService { public string GetDevices() { return "hello world"; } } [ServiceContract] public interface IDeviceService { [OperationContract] string GetDevices(); }
  2. 與主機的圖書館。

     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(); } }
  3. 啟動服務並使用它的桌面應用程序(不起作用)

     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(); }
  4. 控制台應用程序(工作正常)

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM