0

我有一个应用程序,我将通信从 TCPClient 切换到使用 SocketAsyncEventArgs,但是当应用程序运行几个小时时,我确实遇到了一个问题,我似乎找不到它。这是我的堆栈跟踪,有人知道吗?:

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.OutOfMemoryException

Stack:
at System.Threading.ThreadPoolWorkQueue.Enqueue(System.Threading.IThreadPoolWorkItem, Boolean)
at System.Threading.ThreadPool.QueueUserWorkItemHelper(System.Threading.WaitCallback, System.Object, System.Threading.StackCrawlMark ByRef, Boolean)
at System.Threading.ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback, System.Object)
at System.IO.Ports.SerialStream+EventLoopRunner.CallEvents(Int32)
at System.IO.Ports.SerialStream+EventLoopRunner.WaitForCommEvent()
at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()

代码:

public Client(Form1 parent)
        {
            todo = new ArrayList();
            buffert = new List<MsgStruct>();
            this.parent = parent;
            this.ip = ini.GetFromIni("CONFIG", "IP");
            this.port = ini.GetFromIni("CONFIG", "PORT");
            data = new byte[100000];

            // Addres of the host.
            IPAddress[] addressList = host.AddressList;

            // Instantiates the endpoint and socket.
            this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], Convert.ToInt32(port));
            this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            startTimer = new System.Timers.Timer();
            startTimer.Elapsed += new ElapsedEventHandler(startSendLoop);
            startTimer.Interval = 1000;
            startTimer.Start();
            sendTimer = new System.Timers.Timer();
            sendTimer.Elapsed += new ElapsedEventHandler(sendloop);
            sendTimer.Interval = 500;
            sendTimer.Start();
            pingTimer = new System.Timers.Timer();
            pingTimer.Elapsed += new ElapsedEventHandler(pingTimer_Elapsed);
            pingTimer.Interval = 13000;
            pingTimer.Start();

        }


        internal void Disconnect()
        {
            try
            {
                clientSocket.Disconnect(true);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.ToString());
                MessageBox.Show(e.ToString());
            }
        }

        public void Dispose()
        {
            try
            {
                autoConnectEvent.Close();
                autoSendReceiveEvents[SendOperation].Close();
                autoSendReceiveEvents[ReceiveOperation].Close();
                if (this.clientSocket.Connected)
                {
                    this.clientSocket.Close();
                }
            }
            catch (Exception ex)
            {
            }
        }

        public void pingTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            sendPing = true;
        }

        public void startSendLoop(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (!this.clientSocket.Connected)
                {

                    connectArgs = new SocketAsyncEventArgs();

                    connectArgs.UserToken = this.clientSocket;
                    connectArgs.RemoteEndPoint = this.hostEndPoint;
                    connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);

                    clientSocket.ConnectAsync(connectArgs);
                    bool test = autoConnectEvent.WaitOne(5000);

                    gotData = true;
                    lastTime = DateTime.Now;

                }

            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }

        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                // close the socket associated with the client
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    // throws if client process has already closed
                }
                finally
                {
                    if (s.Connected)
                    {
                        s.Close();
                    }
                }
            }

        }

        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                autoConnectEvent.Set();

                // Set the flag for socket connected.
                this.connected = (e.SocketError == SocketError.Success);
            }
            catch (Exception ex)
            {
            }
        }

        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                while (true)
                {
                    if (canReceive)
                    {
                        canReceive = false;
                        string stringData;
                        int recv = 0;
                        for (int i = 0; i < e.Buffer.Length; i++)
                        {
                            if (e.Buffer[i] != 0)
                                recv++;
                            else
                                break;
                        }

                        if (recv > 0)
                        {
                            int count = 0;
                            for (int i = 0; i < data.Length; i++)
                            {
                                if (data[i] != 0)
                                    count++;
                                else
                                    break;
                            }

                            e.Buffer.CopyTo(data, count);

                            lastTime = DateTime.Now;
                            gotData = true;
                            if ((byte)data[count + recv - 1] == (byte)255)
                            {
                                int cnt = -1;
                                for (int i = 0; i < count + recv; i++)
                                {
                                    if (data[i] == (byte)254)
                                    {
                                        cnt = i;
                                        break;
                                    }
                                }
                                int nr = (count + 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);
                                todo.Add(msgs);
                                data = new byte[100000];

                            }
                        }
                        canReceive = true;
                        break;
                    }
                    else
                        Thread.Sleep(10);
                }

                handleToDo();

                autoSendReceiveEvents[SendOperation].Set();
                e.Dispose();

            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }

        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                // Signals the end of send.
                sendSuccess = true;
                autoSendReceiveEvents[ReceiveOperation].Set();

                if (e.SocketError == SocketError.Success)
                {
                    if (e.LastOperation == SocketAsyncOperation.Send)
                    {
                        // Prepare receiving.
                        Socket s = e.UserToken as Socket;

                        byte[] receiveBuffer = new byte[100000];
                        e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                        e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                        s.ReceiveAsync(e);
                    }
                }
                else
                {
                    this.ProcessError(e);
                }
            }
            catch (Exception ex)
            {
            }
        }

        public void sendloop(object sender, ElapsedEventArgs e)
        {

            try
            {

                sendTimer.Enabled = false;
                if (this.clientSocket.Connected)
                {
                    byte[] data = new byte[1024];
                    bool extendedTime = false;
                    DateTime tmpDate = lastTime.AddSeconds(30);
                    if (DateTime.Now > tmpDate)
                    {
                        gotData = false;
                    }

                    if (canUseBuffert && sendSuccess)
                    {
                        canUseBuffert = false;
                        if (buffert.Count > 0)
                        {
                            if (buffert[0] != null && buffert[0].getMsg().Length != 0)
                            {
                                byte[] ba = Encoding.UTF8.GetBytes(buffert[0].getMsg());

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

                                if (buffert[0].canSendByTimeout())
                                {
                                    string crcStr = "?" + buffert[0].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);

                                    this.clientSocket.NoDelay = false;
                                    completeArgs = new SocketAsyncEventArgs();
                                    completeArgs.SetBuffer(fullMsg, 0, fullMsg.Length);
                                    completeArgs.UserToken = this.clientSocket;
                                    completeArgs.RemoteEndPoint = this.hostEndPoint;
                                    completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

                                    sendSuccess = false;
                                    // Start sending asyncronally.
                                    clientSocket.SendAsync(completeArgs);


                                }
                            }
                        }
                        else
                        {
                            extendedTime = true;
                            byte[] bba = Encoding.UTF8.GetBytes("X");
                            this.clientSocket.NoDelay = true;
                            completeArgs = new SocketAsyncEventArgs();
                            completeArgs.SetBuffer(bba, 0, bba.Length);
                            completeArgs.UserToken = this.clientSocket;
                            completeArgs.RemoteEndPoint = this.hostEndPoint;
                            completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

                            sendSuccess = false;
                            // Start sending asyncronally.
                            clientSocket.SendAsync(completeArgs);

                        }
                    }
                    canUseBuffert = true;
                    if (!clientSocket.Connected && !gotData)
                        Disconnect();

                }

                sendTimer.Enabled = true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
                sendTimer.Enabled = true;
            }

        }
4

1 回答 1

4

我会认真看看data = new byte[100000]; 调用您的通信程序。因为它大于 85KB(准确地说是 85,000 字节)内存块,所以您正在填充(并分割)您的 LOH。这可能会导致 OutOfMemoryException 问题。看到这个链接

于 2012-09-17T06:37:45.960 回答