I have a application where I switched out the communication from TCPClient to using SocketAsyncEventArgs, but I do have a problem that occures when the application been running for a few hours, and I cant seem to find it. Here is my Stack Trace, anyone got an idea?:
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()
Code:
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;
}
}
I would have a serious look at the data = new byte[100000]; calls in your communication routines. Because it is larger than 85KB (85,000 bytes to be exact) memory blocks you’re filling up (and fragmenting) your LOH. This can cause OutOfMemoryException issues. See this link