2009-06-05 5 views
-1

Я делаю приложение WPF, и это также сервер WCF, проблема заключается в том, что мне нужно, чтобы ServiceHost был открыт и слушал в порте для клиентов и принимал запросы, как только он начинается, но проблема заключается в том, что если я напишу код, чтобы открыть хост host.open в конструкторе после функции this.InitializeComponent(), он сбой исключается. Если я открываю хост кнопкой и я нажимаю ее после запуска приложения, он работает без проблем.C# WCF host.open failing

Почему это и как я могу решить эту проблему?

Я использую канал tcp.net, я размещаю его в приложении, и исключение, которое я получаю, касается того, что служба уже зарегистрирована.

Исключение на клиентов:

inner exception message :"An existing connection was forcibly closed by the remote host"
error number: 10054
Socket error: System.Net.Sockets.SocketError.ConnectionReset

благодаря

Уолли

конструктор:

public Window1() 
{ 
    this.InitializeComponent(); 
    starthost(); 
} 

private void starthost() 
{ 
    host = new ServiceHost(typeof (Window1), 
          new Uri[]{ new Uri("net.tcp://localhost:8000") }); 

    host.AddServiceEndpoint(typeof(IGanador), new NetTcpBinding(), "Contador"); 
    host.open(); //it fails with this line here but not in a button 
} 
+0

Какой у вас код? Если бы я должен был догадаться, я бы сказал, что звучит так, будто вы кладете код таким образом, чтобы он заканчивался дважды. – tomasr

+0

Я узнал System.ServiceModel вызывает мой конструктор window1 каждый раз, когда он получает запрос клиента, является ли это ошибкой Microsoft? или это ожидаемое поведение? это просто не имеет смысла для меня. – 2009-06-05 20:17:44

+0

Нет, у вас, вероятно, включен режим instanger по умолчанию. Это ожидаемое поведение - каждый запрос от клиента запускает экземпляр сервера. –

ответ

3

Так что я получаю это правильно? Ваш «Window1» - это класс окон WPF, который реализует контракт на обслуживание IGanador? Это кажется немного странным ... как о просто создании собственного класса, например. «GanadorService», который реализует IContador? Тогда этот КЛАСС будет создан/создан для каждого запроса - не ваше окно.

public Window1() 
{ 
    this.InitializeComponent(); 
    starthost(); 
} 

private void starthost() 
{ 
    host = new ServiceHost(typeof (GanadorService), 
          new Uri[]{ new Uri("net.tcp://localhost:8000") }); 

    host.AddServiceEndpoint(typeof(IGanador), new NetTcpBinding(), "Contador"); 
    host.open(); //it fails with this line here but not in a button 
} 


public class GanadorService : IGanador 
{ 
    .... (whatever methods you need) ..... 
} 

Это должно помочь, я надеюсь!

Марк

+0

Я сделал это так, потому что мне нужно сменить gui, и я не был уверен, как передать дескриптор моего окна классу, реализующему интерфейс для Servicehost. Потому что я не вызываю конструктор, но ServiceModel делает это напрямую. Есть ли способ сделать это? благодаря... – 2009-06-05 21:19:09

0

Привет
Я решил проблему спасибо много к комментариям marc_s
Я создал singlenton ServiceHost
добавив следующий атрибут к моему window1

[ServiceBehavior (InstanceContextMode = InstanceContextMode.Single)]

и передавая это в конструктор:

хост = новый ServiceHost ( это, новый товар Uri [] { новый Uri ("сеть.tcp: // localhost: 8000});

он прекрасно работает, потому что у меня есть только один клиент в любом случае

благодаря
это связь с большой статьей с объяснением WCF экземпляра Managment:

http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

0
  1. При использовании Тип контракта сообщения как параметр, Только один параметр может использоваться в услуге. Операция

    [OperationContract] 
    void SaveEmployeeDetails(EmployeeDetails emp); 
    
  2. операция Service либо должна возвращать MessageContract тип или он не должен возвращать никакого значения

    [OperationContract] 
    EmployeeDetails GetEmployeeDetails(); 
    
  3. операция служба будет принимать и возвращать только тип контракта сообщения. Другие типы данных не допускаются.

    [OperationContract] 
    EmployeeDetails ModifyEmployeeDetails(EmployeeDetails emp); 
    

Примечание: Если тип имеет как сообщение и контракт данных, служба эксплуатации будет принимать только контракт сообщение.