【发布时间】:2021-09-12 16:54:36
【问题描述】:
首先,我对 WCF 还很陌生,所以在回复时请记住这一点。
问题是我创建了一个在客户端和服务器之间共享的 WCF 库 (AppCommWcf)。当我使用 AppCommWcf 库编写控制台应用程序并调用它时,它工作正常。当我对测试 WinForms 应用程序执行相同操作时,它工作正常,但是,当我在我们的 WinForms 系统应用程序中使用它时,客户端无法连接到服务器。客户端和服务器都在我的本地机器上运行。我没有在它们各自的 application.exe.config 文件中使用任何值。在你去使用下面的代码尝试和重现之前,正如我之前所说,这在较小的应用程序中运行良好,但不是我们超过一百万行代码的应用程序,所以我希望经验丰富的 WCF 专业人士可以告诉我一些事情至于为什么客户失败了。但我所做的只是在下面 3 个不同的应用程序之间使用相同的确切代码,它只会在我们的系统应用程序中失败。
我运行的测试:
- 系统应用服务器正在运行,系统应用客户端正在运行,客户端无法连接到服务器。
- 控制台作为服务器运行,System app服务器运行(WCF代码注释掉),System App客户端运行,客户端通过WCF连接控制台服务器,完成方法调用。
- 控制台作为客户端运行,System App 服务器正在运行,客户端无法连接到服务器。
根据上面的测试,服务器似乎有问题,但我无法弄清楚为什么它只在系统应用程序服务器中失败,但在控制台和 WinForms 服务器测试应用程序中使用相同的客户端/服务器代码全部。
这是来自 AppCommWcf 库的代码:
Project References:
System
System.Runtime.Serialization
System.ServiceModel
CameraCtrlCommClient.cs:
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:
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)
{
}
}
}
枚举.cs:
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:
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);
}
}
服务器调用代码
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;
}
客户端调用代码:
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 日志的屏幕截图,希望对您有所帮助,如果您需要给定行的详细信息,请告诉我,我会将其发布在 cmets 中,因为这里没有足够的空间来发布整个日志. 服务器日志: 客户日志: 异常文本是: 对“http://localhost:10821/CameraCtrlComm”的 HTTP 请求已超过分配的超时 00:00:14.9990000。分配给此操作的时间可能是较长超时的一部分。
【问题讨论】:
-
事件日志中是否记录了任何异常或错误?随机猜测:您是从网络驱动器还是映射的网络驱动器运行 WinForms 应用程序?
-
事件日志中没有任何内容,将其清除,重新运行应用程序,刷新视图,为空。不,一切都在我的本地计算机上运行,没有网络连接用于 WCF 功能。我使用“h_ttp://localhost:10821/CameraCtrlComm 作为绑定 url,在此评论中有意添加下划线以便显示。