Question:
I have a server application that sends files using Chilkat.Socket.SendBytesAsync(byte[]). The files are about 50MB in size on average.
When I call Task.Run() on the Task object returned from Chilkat.Socket.SendBytesAsync(byte[]), I see memory usage spike about 50MB as expected while the task is running. After the Task is running, I add the Task object to a ConcurrentDictionary collection along with the Socket and in another thread I check the progress of the running Tasks regularly. When each Task is complete, I dispose of the Task object and the Socket object that the Task used.
Unfortunately, memory usage never drops after disposing of the Task and the Socket. Every 50MB file I send yields another 50MB of memory usage. If I use the exact same code but call the synchronous method SendBytes, all memory is freed up after SendBytes is complete and I dispose of the Socket object, so it appears to have something to do with the Asynchronous call.
Following are some of my code snippets.
Here is where I am asynchronously sending the byte[]
Chilkat.Task t = tcpSocket.SendBytesAsync(bytesToSend);
if (!t.Run())
{
LogError("failed to send file: " + tcpSocket.LastErrorText);
return null;
}
_remoteClients_DownloadsInProgress.TryAdd(tcpSocket, t); //add Task and Socket to a collection
Here, on another thread, is where I check the Task progress and dispose of it if it is completed:
foreach(RemoteClient rc in _remoteClients_DownloadsInProgress.Keys)
{
_remoteClients_DownloadsInProgress.TryGetValue(tcpSocket, out taskout);
if ((taskout.StatusInt == 7 && taskout.Finished && taskout.TaskSuccess) )
{
//close the socket
LogDebugInfo("Task Complete!");
try
{
_remoteClients_DownloadsInProgress.TryRemove(tcpSocket, out taskout);
tcpSocket.Close(500);
taskout.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{
LogException(ex);
}
}
}
I am using version 9.5.0.58 of the ChilkatDotNet4.dll
Is there anything in particular I need to do to free up the memory used by the Chilkat dll when calling SendBytesAsync()?
Thanks
I found the cause of the problem. It's a problem specific to passing byte arrays to an Async method in .NET. This problem should be present in all async methods that have byte array arguments (but only for .NET). I should have it fixed for later today, and I'll post a v9.5.0.65 pre-release -- which should be stable because nothing much as occurred yet since v9.5.0.64 (see http://cknotes.com/v9-5-0-65-pre-release-notes/ )
Thanks.. I'll have a look..
Here's a new build that should fix it:
http://chilkatdownload.com/prerelease/chilkatdotnet4-9.5.0-win32.zip
http://chilkatdownload.com/prerelease/chilkatdotnet4-9.5.0-x64.zip
(I haven't tested it yet, but it should work..)
Also, the following Socket methods were added:
These are methods for sending/receiving directly from BinData and StringBuilder objects. See the online reference documentation at https://www.chilkatsoft.com/refdoc/csSocketRef.html
If the 50MB you're sending is data from a file, then you could instead instantiate a Chilkat.BinData object, load it with the file data, and then send it by calling SendBd. This is far better than calling SendBytes. The reason is that w/ SendBytes, the byte array must be marshaled from managed to unmanaged internally. This would cause a temporary spike in memory usage, and of course takes some time. If passing a BinData, then the data stays in unmanaged memory, and there's no memory usage spike, and no marshaling, so it should be faster.
But even if you still use SendBytes, the leak should be fixed.. (I'll verify by testing soon..)