VS 2012中调试/评测/优化C#Windows服务

VS 2012中调试/评测/优化C#Windows服务,c#,sql-server,multithreading,entity-framework,windows-services,C#,Sql Server,Multithreading,Entity Framework,Windows Services,我正在用C#创建一个Windows服务。它的目的是从互联网上的订阅源中获取信息。我使用zeromq的发布/订阅体系结构(我的服务仅为订户)获取数据。要调试服务,我将它“托管”在WPF控制面板中。这允许我启动、运行和停止服务,而无需安装它。我看到的问题是,当我调用stop方法时,服务似乎继续写入数据库。我之所以知道这一点,是因为我将一个Debug.WriteLine()放在了写入的位置 有关该服务的更多信息: 我试图以一种允许它异步写入数据库的方式构造我的服务。这是通过使用线程和线程池的组合来实现

我正在用C#创建一个Windows服务。它的目的是从互联网上的订阅源中获取信息。我使用zeromq的发布/订阅体系结构(我的服务仅为订户)获取数据。要调试服务,我将它“托管”在WPF控制面板中。这允许我启动、运行和停止服务,而无需安装它。我看到的问题是,当我调用stop方法时,服务似乎继续写入数据库。我之所以知道这一点,是因为我将一个
Debug.WriteLine()
放在了写入的位置

有关该服务的更多信息: 我试图以一种允许它异步写入数据库的方式构造我的服务。这是通过使用线程和线程池的组合来实现的

public void StartDataReceiver() // Entry point to service from WPF host
{
    // setup zmq subscriber socket

    receiverThread = new Tread(SpawnReceivers);
    receiverThread.Start();
}

internal void SpawnReceivers()
{
    while(!stopEvent.WaitOne(0))
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessReceivedData), subscriber.Recv()); // subscriber.Recv() blocks when there is no data to receive (according to the zmq docs) so this loop should remain under control, and threads only created in the pool when there is data to process.
    }
}

internal void ProcessReceivedData(Object recvdData)
{
    // cast recvdData from object -> byte[]
    // convert byte[] -> JSON string
    // deserialize JSON -> MyData

    using (MyDataEntities context = new MyDataEntities())
    {
        // build up EF model object

        Debug.WriteLine("Write obj to db...");
        context.MyDatas.Add(myEFModel);
        context.SaveChanges();
    }
}

internal void QData(Object recvdData)
{
    Debug.WriteLine("Queued obj in queue...");
    q.Enqueue((byte[])recvdData);
}

public void StopDataReceiver()
{
    stopEvent.Set();
    receiverThread.Join();
    subscriber.Dispose();
    zmqContext.Dispose();
    stopEvent.Reset();
}
上面的代码是我关心的方法。当我调试WPF主机时,方法
ProcessReceivedData
被设置为在线程池中排队,一切似乎都按预期工作,直到我通过调用
StopDataReceiver
停止服务。据我所知,线程池不再对任何线程排队(我通过在该行上放置断点进行检查),但我继续在输出窗口中看到“将obj写入db…”,当我在调试器中“全部断开”时,
context.SaveChanges()上会出现一个绿色的小箭头行,指示当前暂停执行的位置。当我进行更多测试并让线程池排队时,方法
QData
似乎一切都按预期工作。在停止服务之前,我会在输出窗口中看到“队列中的排队对象…”消息。一旦我在输出窗口中不再显示消息

TL;医生:

我不知道如何确定实体框架是否只是在放慢速度,我看到的消息只是线程池正在清理积压的工作项,或者是否有更大的事情在起作用。我如何着手解决这样的问题

更好的解决方案是像我在
QData
方法中那样将传入的JSON字符串作为byte[]进行排队,然后让线程池使用不同的方法排队以清除队列。我觉得这个解决方案只会转移问题,而不会真正解决问题

另一个解决方案是编写一个新的服务来专门清除该队列吗?我在编写另一个服务时遇到的问题是,我可能必须使用WCF(或者可能是zmq)在两个服务之间进行通信,这显然会增加开销,并可能降低性能


我认为所有这些中的关键部分是足够快地将数据从网络上传输出去,因为如果我的订阅者跟不上,我订阅的发布者将开始丢弃消息。

您可能有未完成的回调,您使用
ThreadPool.QueueUserWorkItem
排队。即使您停止了一些线程,回调的线程仍然到达,当数据进入时,它们
ProcessReceivedData
@Pawel:我不确定我是否理解您的意思。你是说即使我已经停止了对工作项的排队,仍然有一些剩余?因为套接字上的
Recv()
方法在没有数据时应该被阻塞。这意味着除非有事情要做,否则工作项不会排队。我的感觉是,当您停止排队工作项时,队列中已经有一些请求已被发送。这些工作项接收响应并处理接收到的内容。即使recv()正在阻塞,您基本上也会在recv()上阻塞许多工作项,当recv()取消阻塞时,这些工作项会被唤醒。我一直在使用Window stask manager中的网络监视器,当我停止服务时,通信量将变为零。所以写下这些变化肯定要花很长时间。