首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Wcf代码适用于控制台和WinForms应用程序(小型测试应用程序),但不适用于系统WinForms应用程序。

Wcf代码适用于控制台和WinForms应用程序(小型测试应用程序),但不适用于系统WinForms应用程序。
EN

Stack Overflow用户
提问于 2021-06-30 14:04:44
回答 1查看 29关注 0票数 0

首先,我对WCF相当陌生,所以在回复时请记住这一点。

问题是我创建了一个WCF库(AppCommWcf),它在客户机和服务器之间共享。当我使用AppCommWcf库编写控制台应用程序并调用它时,它可以正常工作。当我对测试WinForms应用程序执行相同的操作时,它可以正常工作,但是,当我在WinForms系统应用程序中使用它时,客户端无法连接到服务器。客户端和服务器都在我的本地机器上运行。我不会在他们各自的application.exe.config文件中使用任何值。在您开始使用下面的代码来尝试和复制之前,正如我之前说过的,这在较小的应用程序中很好,但我们的代码应用程序超过一百万行,所以我希望经验丰富的WCF专业人员能够告诉我一些事情,找出客户端失败的原因。但是我所做的只是使用下面三个不同应用程序之间相同的代码,它只在我们的系统应用程序中失败。

我做过的测试:

系统应用程序服务器运行,系统应用程序客户端运行,客户端无法连接到作为服务器运行的server.

  • Console,系统应用服务器运行,系统应用程序客户端运行,客户端通过连接到控制台服务器,并完成方法调用。
  • 控制台作为客户端运行,系统应用服务器运行,客户端无法连接到服务器。

基于上面的测试,服务器似乎出了问题,但我不知道为什么它只在系统应用服务器上失败,而是在控制台和WinForms服务器上使用所有这些应用程序中相同的客户机/服务器代码进行测试。

下面是来自AppCommWcf库的代码:

代码语言:javascript
复制
Project References:
System
System.Runtime.Serialization
System.ServiceModel

CameraCtrlCommClient.cs:

代码语言:javascript
复制
using System.ServiceModel;

namespace AppCommWcf
{
    public partial class CameraCtrlCommClient : ClientBase<ICameraCtrlComm>, ICameraCtrlComm
    {
        public CameraCtrlCommClient(string bindUrl) : base(new WSHttpBinding(), new EndpointAddress(bindUrl)) { }

        public LockRequestResponse RequestLock(LockTypeWcf lckType, string camName, int stationId, string userName, bool takeCtrlIfLocked)
        {
            return base.Channel.RequestLock(lckType, camName, stationId, userName, takeCtrlIfLocked);
        }
    }
}

CameraCtrlCommServer.cs:

代码语言:javascript
复制
using System;
using System.ServiceModel;

namespace AppCommWcf
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class CameraCtrlCommServer : ICameraCtrlComm
    {
        public delegate LockRequestResponse LockEventHandler(LockTypeWcf lckType, string camName, int stationId, string userName, bool takeCtrlIfLocked);

        public event LockEventHandler LockRequested;
        static ServiceHost m_svcHost;

        CameraCtrlCommServer() { }

        public string BindingUrl { get; private set; }

        public void Close()
        {
            if (m_svcHost != null)
            {
                m_svcHost.Close();
                m_svcHost = null;
            }
        }

        public LockRequestResponse RequestLock(LockTypeWcf lckType, string camName, int stationId, string userName, bool takeCtrlIfLocked)
        {
            return LockRequested.Invoke(lckType, camName, stationId, userName, takeCtrlIfLocked);
        }

        public static CameraCtrlCommServer StartServiceHost(string bindUrl)
        {
            CameraCtrlCommServer result = null;

            if (m_svcHost == null)
            {
                result = new CameraCtrlCommServer { BindingUrl = bindUrl };
                m_svcHost = new ServiceHost(result, new Uri(bindUrl))
                {
                    OpenTimeout = new TimeSpan(0, 0, 30),
                    CloseTimeout = new TimeSpan(0, 0, 10)
                };

                m_svcHost.AddServiceEndpoint(typeof(ICameraCtrlComm), new WSHttpBinding(), bindUrl);
                m_svcHost.Faulted += OnSvcHostFaulted;
                m_svcHost.Opened += OnSvcHostOpened;
                m_svcHost.Closing += OnSvcHostClosing;
                m_svcHost.Closed += OnSvcHostClosed;
                m_svcHost.UnknownMessageReceived += OnSvcHostUnknownMsgRecvd;

                m_svcHost.Open();
            }
            else
            {
                throw new Exception("The service host has already been started.");
            }

            return result;
        }

        static void OnSvcHostUnknownMsgRecvd(object sender, UnknownMessageReceivedEventArgs e)
        {
        }

        static void OnSvcHostClosed(object sender, EventArgs e)
        {
        }

        static void OnSvcHostClosing(object sender, EventArgs e)
        {
        }

        static void OnSvcHostOpened(object sender, EventArgs e)
        {
        }

        static void OnSvcHostFaulted(object sender, EventArgs e)
        {
        }
    }
}

Enums.cs:

代码语言:javascript
复制
using System.Runtime.Serialization;

namespace AppCommWcf
{
    /// <summary>
    /// The type of lock being requested.  These values must match BMS.ElectroOptic.C4IAppOffEnum.BMSSensorLockTypeEnum
    /// </summary>
    [DataContract(Name = "LockTypeWcf", Namespace = "http://schemas.datacontract.org/2004/07/AppCommWcf")]
    public enum LockTypeWcf : int
    {
        /// <summary>
        /// The camera is not locked.
        /// </summary>
        [EnumMember]
        NotLocked = 0,
        /// <summary>
        /// A manual lock was performed by clicking the Lock toolbar button on a video, cannot be overridden except by another
        /// user or an <see cref="Entity"/> lock.
        /// </summary>
        [EnumMember]
        Manual,
        /// <summary>
        /// An action was performed that required an auto-lock and an auto-unlock if not other action is taken within
        /// the time specified in C4IAppSimple.BMSSEOMngrParamsOfRoot.AutoUnlockTimeout.  Can be overridden by another user
        /// or <see cref="Manual"/> or <see cref="Entity"/>.
        /// </summary>
        [EnumMember]
        Auto,
        /// <summary>
        /// A lock was performed by an entity action, i.e. House Call, Line Scan or Investigation.  Can be overridden by
        /// another user or <see cref="Manual"/> or <see cref="Auto"/>.
        /// </summary>
        [EnumMember]
        Entity
    }

    #region LockPromptResponse enum
    /// <summary>
    /// The possible responses from <see cref="BMSEOMngr.RequestCameraLock(BMSSensorLockTypeEnum, BMSEOChannelEnt, int, string)"/>
    /// or <see cref="BMSEOMngr.RequestCameraLock(BMSSensorLockTypeEnum, InfSensorId, int, string)"/>.
    /// </summary>
    [DataContract(Name = "LockRequestResponse", Namespace = "http://schemas.datacontract.org/2004/07/AppCommWcf")]
    public enum LockRequestResponse
    {
        /// <summary>
        /// The video is not locked.
        /// </summary>
        [EnumMember]
        NotLocked = 0,
        /// <summary>
        /// The video is locked by the current user.
        /// </summary>
        [EnumMember]
        LockedByCurrentUser,
        /// <summary>
        /// The video is locked by a different user.
        /// </summary>
        [EnumMember]
        LockedByOtherUser
    }
    #endregion

}

ICameraCtrlComm.cs:

代码语言:javascript
复制
using System.ServiceModel;

namespace AppCommWcf
{
    [ServiceContract]
    public interface ICameraCtrlComm
    {
        [OperationContract(Action = "http://tempuri.org/ICameraLockComm/RequestLock", ReplyAction = "http://tempuri.org/ICameraLockComm/RequestLockResponse")]
        LockRequestResponse RequestLock(LockTypeWcf lckType, string camName, int stationId, string userName, bool takeCtrlIfLocked);
    }
}

服务器调用代码

代码语言:javascript
复制
using AppCommWcf;

CameraCtrlCommServer m_camCtrlServer;
Main()
{
    m_camCtrlServer = CameraCtrlCommServer.StartServiceHost(bindUrl);
    m_camCtrlServer.LockRequested += OnServerLockRequested;
}

LockRequestResponse OnServerLockRequested(LockTypeWcf lckType, string camName, int stationId, string userName, bool takeCtrlIfLocked)
{
    return LockRequestResponse.LockedByCurrentUser;
}

客户端调用代码:

代码语言:javascript
复制
using AppCommWcf;
using System.ServiceModel.Channels;

CameraCtrlCommClient m_camCtrlClient;

void Main()
{
    TimeSpan timeout = new TimeSpan(0, 0, 15); //So I don't have to wait a minute to find out it failed to connect.

    m_camCtrlClient = new CameraCtrlCommClient(bindUrl);
    Binding binding = m_camCtrlClient.Endpoint.Binding;

    binding.OpenTimeout = timeout;
    binding.ReceiveTimeout = timeout;
    binding.SendTimeout = timeout;

}

这里是WCF日志的屏幕截图,希望它会有所帮助,如果您想知道给定行的细节,请告诉我,我会在评论中发布它,因为我在这里没有足够的空间来发布整个日志。服务器日志:

客户日志:

异常文本是:对'http://localhost:10821/CameraCtrlComm‘的HTTP请求超过了分配的超时00:00:14.9990000。分配给此操作的时间可能是较长超时的一部分。

EN

回答 1

Stack Overflow用户

发布于 2021-06-30 18:39:45

问题是,我在一个非windows消息循环线程上实例化ServiceHost。一旦我创建了自己的线程,并使用Application.Run让它在该线程中等待,直到应用程序退出,它就工作了。我希望这能帮到别人。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68196327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档