首先,我对WCF相当陌生,所以在回复时请记住这一点。
问题是我创建了一个WCF库(AppCommWcf),它在客户机和服务器之间共享。当我使用AppCommWcf库编写控制台应用程序并调用它时,它可以正常工作。当我对测试WinForms应用程序执行相同的操作时,它可以正常工作,但是,当我在WinForms系统应用程序中使用它时,客户端无法连接到服务器。客户端和服务器都在我的本地机器上运行。我不会在他们各自的application.exe.config文件中使用任何值。在您开始使用下面的代码来尝试和复制之前,正如我之前说过的,这在较小的应用程序中很好,但我们的代码应用程序超过一百万行,所以我希望经验丰富的WCF专业人员能够告诉我一些事情,找出客户端失败的原因。但是我所做的只是使用下面三个不同应用程序之间相同的代码,它只在我们的系统应用程序中失败。
我做过的测试:
系统应用程序服务器运行,系统应用程序客户端运行,客户端无法连接到作为服务器运行的server.
基于上面的测试,服务器似乎出了问题,但我不知道为什么它只在系统应用服务器上失败,而是在控制台和WinForms服务器上使用所有这些应用程序中相同的客户机/服务器代码进行测试。
下面是来自AppCommWcf库的代码:
Project References:
System
System.Runtime.Serialization
System.ServiceModelCameraCtrlCommClient.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)
{
}
}
}Enums.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日志的屏幕截图,希望它会有所帮助,如果您想知道给定行的细节,请告诉我,我会在评论中发布它,因为我在这里没有足够的空间来发布整个日志。服务器日志:

客户日志:

异常文本是:对'http://localhost:10821/CameraCtrlComm‘的HTTP请求超过了分配的超时00:00:14.9990000。分配给此操作的时间可能是较长超时的一部分。
发布于 2021-06-30 18:39:45
问题是,我在一个非windows消息循环线程上实例化ServiceHost。一旦我创建了自己的线程,并使用Application.Run让它在该线程中等待,直到应用程序退出,它就工作了。我希望这能帮到别人。
https://stackoverflow.com/questions/68196327
复制相似问题