我有一个在服务器上托管 WCF 服务的 Windows 服务。我正在使用InstanceContextMode.PerSession
属性。根据我的要求,服务运行良好。
我现在想为 WCF 服务实现视觉反馈,例如记录器,最好在 Windows 窗体的列表框中。我希望所有客户的所有呼叫和后续操作都记录在此表单中。我读到有一个服务的用户界面不是一个好主意。有人可以指出我以线程安全的方式实现这一目标的方向。
我有一个在服务器上托管 WCF 服务的 Windows 服务。我正在使用InstanceContextMode.PerSession
属性。根据我的要求,服务运行良好。
我现在想为 WCF 服务实现视觉反馈,例如记录器,最好在 Windows 窗体的列表框中。我希望所有客户的所有呼叫和后续操作都记录在此表单中。我读到有一个服务的用户界面不是一个好主意。有人可以指出我以线程安全的方式实现这一目标的方向。
我认为最简单的答案就是这个。基本上,您可以做的是为您的 wcf 服务定义一个自定义跟踪侦听器。您可以修改示例以获得所需的结果。
自定义跟踪实现如下所示:
namespace WcfTrace.Trace
{
public class WebTraceListener : TraceListener
{
public override void Write(string message)
{
//write you custom code here
Debug.WriteLine(message);
}
public override void WriteLine(string message)
{
//write your custom code here
Debug.WriteLine(message);
}
}
}
您的服务主机上的配置必须包括以下内容:
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml" type="WcfTrace.Trace.WebTraceListener,WcfTrace.Trace" />
</sharedListeners>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="false"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="300000"
maxSizeOfMessageToLog="200000"/>
</diagnostics>
</system.serviceModel>
我个人喜欢这个想法,独立于客户端的跟踪器类(您提到的带有列表框的应用程序)可以使用来自此自定义跟踪实现的信息,以及将来可以做的任何其他事情。
该服务没有 UI,但主机可以。
这只是一个控制台主机,但它显示来自服务的文本。
Service 中的那些 Console.WriteLine 显示在主机中。
namespace MagicEightBallServiceHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**** Console Based WCF Host *****");
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
{
serviceHost.Open();
Console.WriteLine("The service is running");
Console.ReadLine();
}
[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerSession)]
public class MagicEightBallService : IEightBall, IDisposable
{
private DateTime serviceStartTime;
public void Dispose()
{
Console.WriteLine("Eightball dispose ... " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString());
}
public MagicEightBallService()
{
serviceStartTime = DateTime.Now;
Console.WriteLine("Eightball awaits your question " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString());
}
public string ObtainAnswerToQuestion(string userQuestion)
{
Console.WriteLine("Eightball ObtainsAnser " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString());
return "maybe " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString() ;
}
您所说的本质上是让您的 Windows 服务中的 WCF 服务在发生“有趣”的事情时向 UI 前端提供事件通知。幸运的是,有一个Publish-Subscribe Framework由Programming WCF Services的作者Juval Lowy开发。详细信息在这篇出色的 MSDN 文章中进行了描述,源代码可在Lowy 的网站上免费获得。
这个框架的巧妙之处在于它将发布者(例如,您的 Windows 服务中的 WCF 服务)与任何订阅者(例如,您的 GUI)分离。发布者“发布”Pub/Sub 服务感兴趣的事件,该服务始终可用。从发布者的角度来看,有没有订阅者并不重要。Pub/Sub 服务负责将事件路由到所有注册的订阅者。这样,您的 Windows 服务中的 WCF 服务会在事件发生时发布事件,您的 GUI 将在加载/退出时订阅/取消订阅 Pub/Sub 服务,并且 Pub/Sub 服务将在事件发生时通知您的 GUI。
我在我的项目中使用了这个设置,它工作得非常好。
编辑: 我理解希望拥有自己的 UI 来显示来自 Windows 服务托管的 WCF 服务的事件。另一种选择是利用可从 Windows 本机事件查看器 (eventvwr.msc) 访问的应用程序日志。如果这种方法可以接受,请查看我在此处的说明,了解如何从您的 Windows 服务进行设置。
使用log4net之类的东西来记录您要显示的代表感兴趣的 Web 服务活动的信息。通过使用 log4net,您只需更改配置文件即可过滤记录的信息类型。您还可以通过登录配置文件来更改信息的位置和方式。您可以为 log4net 配置的附加程序之一是SysLogAppender。这会将日志信息发送到远程SysLog 服务器(它也可以与 Web 服务一起部署)。有许多 SysLog 服务器可用,例如Kiwi这将提供日志事件的滚动显示,并提供对某些事件的过滤器和操作(例如:发生错误时向管理员发送电子邮件)。还有可用的开源 SysLog 服务器。这有效地将日志信息的查看和处理与实际日志记录分离。