Вызов службы WCF с использованием NetTcpBinding из той же winform - PullRequest
0 голосов
/ 25 апреля 2018

Привет всем, у меня есть следующий код, который позволяет мне запускать временную веб-службу для служб WCF без подмены IIS Express.

Однако приведенный ниже код прекрасно работает , если У меня есть выборка данных в другой winform.Копирование того же кода в winform-службу WCF приводит к зависанию при попытке отправить индексный номер пациента.

Код класса (Class1.cs):

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;

/*
    HOW TO HOST THE WCF SERVICE IN THIS LIBRARY IN ANOTHER PROJECT
    You will need to do the following things: 
    1)    Add a Host project to your solution
        a.    Right click on your solution
        b.    Select Add
        c.    Select New Project
        d.    Choose an appropriate Host project type (e.g. Console Application)
    2)    Add a new source file to your Host project
        a.    Right click on your Host project
        b.    Select Add
        c.    Select New Item
        d.    Select "Code File"
    3)    Paste the contents of the "MyServiceHost" class below into the new Code File
    4)    Add an "Application Configuration File" to your Host project
        a.    Right click on your Host project
        b.    Select Add
        c.    Select New Item
        d.    Select "Application Configuration File"
    5)    Paste the contents of the App.Config below that defines your service endoints into the new Config File
    6)    Add the code that will host, start and stop the service
        a.    Call MyServiceHost.StartService() to start the service and MyServiceHost.EndService() to end the service
    7)    Add a Reference to System.ServiceModel.dll
        a.    Right click on your Host Project
        b.    Select "Add Reference"
        c.    Select "System.ServiceModel.dll"
    8)    Add a Reference from your Host project to your Service Library project
        a.    Right click on your Host Project
        b.    Select "Add Reference"
        c.    Select the "Projects" tab
    9)    Set the Host project as the "StartUp" project for the solution
        a.    Right click on your Host Project
        b.    Select "Set as StartUp Project"

    ################# START MyServiceHost.cs #################

    using System;
    using System.ServiceModel;

    // A WCF service consists of a contract (defined below), 
    // a class which implements that interface, and configuration 
    // entries that specify behaviors and endpoints associated with 
    // that implementation (see <system.serviceModel> in your application
    // configuration file).

    internal class MyServiceHost
    {
        internal static ServiceHost myServiceHost = null;

        internal static void StartService()
        {
            //Consider putting the baseAddress in the configuration system
            //and getting it here with AppSettings
            Uri baseAddress = new Uri("http://localhost:8080/service1");

            //Instantiate new ServiceHost 
            myServiceHost = new ServiceHost(typeof(TestService.service1), baseAddress);

            //Open myServiceHost
            myServiceHost.Open();
        }

        internal static void StopService()
        {
            //Call StopService from your shutdown logic (i.e. dispose method)
            if (myServiceHost.State != CommunicationState.Closed)
                myServiceHost.Close();
        }
    }

    ################# END MyServiceHost.cs #################
    ################# START App.config or Web.config #################

    <system.serviceModel>
    <services>
         <service name="TestService.service1">
           <endpoint contract="TestService.IService1" binding="wsHttpBinding"/>
         </service>
       </services>
    </system.serviceModel>

    ################# END App.config or Web.config #################

*/
namespace TestService
{
    // You have created a class library to define and implement your WCF service.
    // You will need to add a reference to this library from another project and add 
    // the code to that project to host the service as described below.  Another way
    // to create and host a WCF service is by using the Add New Item, WCF Service 
    // template within an existing project such as a Console Application or a Windows 
    // Application.

    [ServiceContract()]
    public interface IService1
    {
        [OperationContract]
        Patient GetPatient(Int32 index);

        [OperationContract]
        void SetPatient(Int32 index, Patient patient);
    }

    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class PatientService : IService1
    {
        Patient[] pat = null;

        public PatientService()
        {
            pat = new Patient[3];

            pat[0] = new Patient();
            pat[0].FirstName = "Bob";
            pat[0].LastName = "Chandler";

            pat[1] = new Patient();
            pat[1].FirstName = "Joe";
            pat[1].LastName = "Klink";

            pat[2] = new Patient();
            pat[2].FirstName = "Sally";
            pat[2].LastName = "Wilson";
        }

        public Patient GetPatient(Int32 index)
        {
            if (index <= pat.GetUpperBound(0) && index > -1)
                return pat[index];
            else
                return new Patient();
        }

        public void SetPatient(Int32 index, Patient patient)
        {
            if (index <= pat.GetUpperBound(0) && index > -1)
                pat[index] = patient;
        }
    }

    [DataContract]
    public class Patient
    {
        string firstName;
        string lastName;

        [DataMember]
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        [DataMember]
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
    }
}

Код услуги (Form1.cs):

using System;
using System.Windows.Forms;
using System.ServiceModel;

namespace TestService
{
    public partial class Form1 : Form
    {
        bool serviceStarted = false;
        ServiceHost myServiceHost = null;
        NetTcpBinding binding;
        Uri baseAddress = new Uri("net.tcp://localhost:2202/PatientService");

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (serviceStarted)
            {
                myServiceHost.Close();
                serviceStarted = false;
                button1.Text = "Start Service";
            }
            else
            {
                binding = new NetTcpBinding();
                myServiceHost = new ServiceHost(typeof(PatientService), baseAddress);
                myServiceHost.AddServiceEndpoint(typeof(IService1), binding, baseAddress);

                myServiceHost.Open();

                serviceStarted = true;
                button1.Text = "Stop Service";    
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            IService1 patientSvc = null;
            EndpointAddress address = new EndpointAddress(baseAddress);
            ChannelFactory<IService1> factory = new ChannelFactory<IService1>(binding, address);
            patientSvc = factory.CreateChannel();

            Patient patient = patientSvc.GetPatient(Convert.ToInt32(textBox1.Text));

            if (patient != null)
            {
                textBox2.Text = patient.FirstName;
                textBox3.Text = patient.LastName;
            }
        }
    }

    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

enter image description here

Кодовая строка здесь:

Patient patient = patientSvc.GetPatient(Convert.ToInt32(textBox1.Text));

- это место, где она зависает.Опять же, это тот же код, что и в другой winform, и работает .Просто, когда его использование внутри самой службы по какой-то причине не работает одинаково ??

Ошибка, которую он дает, такова:

System.TimeoutException: 'Эта операция запроса, отправленная на net.tcp: // localhost: 2202 / PatientService, не получила ответа в течение настроенного времени ожидания (00:01:00).Время, отведенное для этой операции, могло быть частью более длительного времени ожидания.Это может быть связано с тем, что служба все еще обрабатывает операцию или службе не удалось отправить ответное сообщение.Пожалуйста, подумайте об увеличении времени ожидания операции (приведя канал / прокси к IContextChannel и установив свойство OperationTimeout) и убедитесь, что служба может подключиться к клиенту.чтобы заставить его работать?

Это другой код winform:

using System;
using System.Windows.Forms;
using System.ServiceModel;
using TestService;

namespace TestClient
{
    public partial class Form1 : Form
    {
        IService1 patientSvc = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            EndpointAddress address = new EndpointAddress(new Uri("net.tcp://localhost:2202/PatientService"));
            NetTcpBinding binding = new NetTcpBinding();
            ChannelFactory<IService1> factory = new ChannelFactory<IService1>(binding, address);
            patientSvc = factory.CreateChannel();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Patient patient = patientSvc.GetPatient(Convert.ToInt32(textBox1.Text));

            if (patient != null)
            {
                textBox2.Text = patient.FirstName;
                textBox3.Text = patient.LastName;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Patient patient = new Patient();
            patient.FirstName = textBox2.Text;
            patient.LastName = textBox3.Text;

            patientSvc.SetPatient(Convert.ToInt32(textBox1.Text), patient);
        }
    }
}

Код TestClient (Program.cs):

using System;
using System.Windows.Forms;

namespace TestClient
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

enter image description here

1 Ответ

0 голосов
/ 26 апреля 2018

Понял!Спасибо @Eser за подсказку:)

private void button3_Click(object sender, EventArgs e)
{
    IService1 patientSvc = null;
    EndpointAddress address = new EndpointAddress(baseAddress);
    ChannelFactory<IService1> factory = new ChannelFactory<IService1>(binding, address);
    patientSvc = factory.CreateChannel();

    Thread thread = new Thread(() => sendData(patientSvc));
    thread.Start();            
}

delegate void SetTextCallback(string text, bool isTxt2);

private void SetText(string text, bool isTxt2)
{
    if (isTxt2)
    {
        if (this.textBox2.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            textBox2.Invoke(d, new object[] { text, isTxt2 });
        }
        else
        {
            textBox2.Text = text;
        }
    } else {
        if (this.textBox3.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            textBox2.Invoke(d, new object[] { text, isTxt2 });
        } else {
            this.textBox3.Text = text;
        }
    }
}

public void sendData(IService1 patientSvc)
{
    Patient patient = patientSvc.GetPatient(Convert.ToInt32(textBox1.Text));

    if (patient != null)
    {
        SetText(patient.FirstName, true);
        SetText(patient.LastName, false);
    }
}
...