0

我有一个相当大的 C# 服务,它作为一个服务器应用程序同时与几个(大约 5 个)客户端进行通信。每个客户端都是一个线程,主要将数据放入 Access 数据库并从 Access 数据库中取出数据。该服务在启动时运行良好,但几天后 CPU 变得疯狂(上升 99%)并且服务开始变慢很多。我不知道是什么原因造成的......无论如何,有没有看到占用 CPU 的服务中的什么,什么函数 och 线程?不知道如何更好地描述它,但如果您需要更多信息来帮助,请提出问题!:)

/缺口

编辑:添加了关于我如何创建线程以及它们做什么的代码......(在我使用 Process Expolorer 之后,我注意到我已经运行了很多)

private void ListenForClients()
{
            this.tcpListener.Start();

            while (true)
            {
                TcpClient client = this.tcpListener.AcceptTcpClient();

                Connection c = new Connection(this.parent);
                Thread clientThread = new Thread(new ParameterizedThreadStart(c.HandleClientComm));

                threadCollection.Add(clientThread);
                clientThread.Start(client);
            }
}

public void HandleClientComm(object client)
    {
        try
        {

            TcpClient server = (TcpClient)client;

            NetworkStream ns = server.GetStream();
            byte[] data = new byte[1024];
            string input, stringData;

            while (true)
            {
                try
                {
                    data = new byte[1024];
                    if (ns.DataAvailable && ns.CanRead)
                    {
                        int recv = ns.Read(data, 0, data.Length);
                        if (recv > 0)
                        {
                            if ((byte)data[recv - 1] == (byte)255)
                            {
                                int cnt = -1;
                                for (int i = 0; i < recv; i++)
                                {
                                    if (data[i] == (byte)254)
                                        cnt = i;
                                }

                                int nr = recv - cnt - 2;
                                byte[] tmp = new byte[nr];

                                for (int i = 0; i < nr; i++)
                                {
                                    tmp[i] = data[cnt + i + 1];
                                }
                                string crc = Encoding.UTF8.GetString(tmp);
                                stringData = Encoding.UTF8.GetString(data, 0, cnt);

                                MsgStruct msgs = new MsgStruct(stringData);
                                msgs.setCrc(crc);
                                Thread.Sleep(200);

                                addTodo(msgs);
                            }
                        }


                    }
                    if (parent.cStructHandler.gotMsg(this.ID))
                    {
                        MsgStruct tmpCs = parent.cStructHandler.getNextMsg(this.ID);

                        if (tmpCs.getMsg().Length != 0 && ns.CanWrite)
                        {
                            byte[] ba = Encoding.UTF8.GetBytes(tmpCs.getMsg());

                            if (tmpCs.getCrc() == "")
                            {
                                ulong tmp = CRC.calc_crc(ba, ba.Length);
                                tmpCs.setCrc(tmp.ToString("X"));
                            }

                            if (tmpCs.canSendByTimeout())
                            {
                                string crcStr = "?" + tmpCs.getCrc() + "?";
                                byte[] bb = Encoding.UTF8.GetBytes(crcStr);
                                crcStr = Encoding.UTF8.GetString(bb);
                                byte[] fullMsg = new byte[ba.Length + bb.Length];
                                bb[0] = 254;
                                bb[bb.Length - 1] = 255;

                                ba.CopyTo(fullMsg, 0);
                                bb.CopyTo(fullMsg, ba.Length);
                                string s = System.Text.UTF8Encoding.ASCII.GetString(fullMsg);

                                ns.Write(fullMsg, 0, fullMsg.Length);
                                Thread.Sleep(200);
                                if (!tmpCs.isAckNeeded())
                                    parent.cStructHandler.removeNextMsg(this.ID);
                            }
                        }
                    }

                    Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    break;
                }

            }
            ns.Close();
            server.Close();

        }
        catch (Exception e)
        {
        }
    }
4

3 回答 3

1

我建议您使用某种跟踪,只是为了看看您的应用程序在做什么:

这是一个简单的dot net log 4 net教程的日志框架

并且:正如您所说,这是一个长时间运行的服务器进程,我建议使用滚动日志(即,如果日志文件有一定数量的行,则使用新文件)。log4net RollingFileAppender 派上用场了。

您应该对标准情况使用高级跟踪(即,当一切正常时)并能够在需要时(即当您的服务器进程失控时)切换到具有更多输出的较低级别。

而且,当然,您可以通过jetbrains 工具查看

同样强烈推荐的是那些 RedGate 工具:ANTS 性能分析器点网反射器

编辑

差点忘了提:我最喜欢的工具之一:Process Explorer

编辑2

如果工作完成,我认为你需要休息一下才能让这段时间保持真实

于 2012-06-14T10:06:32.890 回答
0

尝试检查打开的句柄(文件)。我打赌你忘了释放原生资源(忘了using建设)

于 2012-06-14T10:26:00.593 回答
0

您的代码中的主要问题是您无限期地生成线程并且可能根本没有在 threadCollection 中释放它们。

也许ThreadPool.QueueUserWorkItem "fire & forget" 在你的情况下更好?

于 2012-06-14T16:35:58.257 回答