自托管的WCF服务的可视化反馈

3
我有一个在服务器上托管WCF服务的Windows服务。我使用InstanceContextMode.PerSession属性。这些服务按照我的要求正常运行。
现在,我想为WCF服务实现一个可视化反馈,比如记录器,最好是在Windows窗体中的列表框中。我希望所有来自所有客户端的调用和随后的操作都记录在此表单中。我读到过为服务添加UI不是一个好主意。有人可以指导我以线程安全的方式实现这一目标吗?
4个回答

4
我认为最简单的答案是这篇文章。 基本上,您可以为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>

我个人很喜欢这个想法,独立于客户端的追踪器类(你提到的列表框应用程序)可以使用此自定义跟踪实现中的信息,以及未来的任何其他东西。


快速问题,我能否通过这种机制记录自定义消息。换句话说,我是否可以在我的WCF服务请求中发出自定义消息,以便跟踪侦听器可以捕获。 - swiftgp
不好意思,使用这种方法,你只能通过 messageLogging 配置标签进行所有的自定义。 - danielQ

1

该服务没有用户界面,但主机可能有。

这只是一个控制台主机,但它会显示来自服务的文本。

服务中的 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服务不断调用它吗? - swiftgp
@user1556110,不行。这样做是错误的。由于服务隔离(我认为是在Vista中引入),Windows服务不能再直接与桌面交互。因此,从您的Windows服务写入控制台将无法帮助您。简而言之,您需要开发一个UI,可以使用某些IPC机制(例如套接字、管道、共享内存等)与您的Windows服务通信。我在我的答案中提供了如何通过WCF完成此操作的示例。 - Matt Davis
一个Windows服务中的Service没有UI。这个简单的技巧只在控制台托管服务时有效。虽然有限但很容易实现。 - paparazzo

1

你所说的实质上是让你的 WCF 服务在 Windows 服务内,当发生“有趣”的事情时,向 UI 前端提供事件通知。幸运的是,Juval Lowy 开发了一个发布-订阅框架,他也是《Programming WCF Services》的作者。 这篇出色的 MSDN 文章中详细介绍了细节,源代码可以在Lowy 的网站上免费获取。

这个框架的好处在于它将发布者(例如您的 Windows 服务中的 WCF 服务)与任何订阅者(例如您的 GUI)解耦。发布者“发布”感兴趣的事件到始终可用的 Pub/Sub 服务。从发布者的角度来看,是否有订阅者并不重要。Pub/Sub 服务负责将事件路由到所有已注册的订阅者。通过这种方式,您的 Windows 服务中的 WCF 服务会在事件发生时发布事件,您的 GUI 在加载/退出时将订阅/取消订阅 Pub/Sub 服务,并且 Pub/Sub 服务将在事件发生时通知您的 GUI。
我在我的项目中使用了这个设置,效果非常好。
编辑:我理解您想要拥有自己的 UI 来显示来自 Windows 服务托管的 WCF 服务的事件的愿望。另一个选择是利用可以从 Windows 原生事件查看器(eventvwr.msc)访问的应用程序日志。如果这种方法可行,请查看我在此处的说明链接1,了解如何从您的 Windows 服务中设置它。

0
使用类似log4net的东西来记录您想要显示的代表感兴趣的Web服务活动的信息。通过使用log4net,您可以通过更改配置文件来过滤要记录的信息类型。您还可以在配置文件中更改要记录信息的位置和方式。您可以为log4net配置的一个附加程序是SysLogAppender。这将把日志信息发送到远程SysLog Server(它也可以与Web服务一起部署)。有许多可用的SysLog服务器,例如Kiwi,它将提供日志事件的滚动显示,并为某些事件提供过滤器和操作(例如:在发生错误时向管理员发送电子邮件)。还有开源SysLog Severs可用。这有效地解除了查看和处理日志信息与实际记录之间的耦合。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接