Reputation: 75
Hello I have made a very simple program there gets some pictrue addresses over TCP-IP and shows them on the screen. My problem is that memory is left behind every time I update a picture which esentially leaves me with a memory overload.
I have been looking around for an awnser and concluded that I might need to use the function Dispose, my oproblem is that I get the following error when I try to implement it
error C2039: 'Dispose' : is not a member of 'System::Windows::Forms::PictureBox' Note that I'm using visual studio 2008 and it accually sugest to function to me.
What I'm looking for is the correct way of clearing memory when I want to load a new picture.
This is my code, and thanks to anyone there takes the time to look at my problem
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
pictureBoxArrayLeft->Resize(pictureBoxArrayLeft,15);
pictureBoxArrayRight->Resize(pictureBoxArrayRight,15);
IPAddress^ listenInterface = IPAddress::Any;//Parse("127.0.0.1");
int listenPort = 12000;
int bufferSize = 4096;
sendBuffer = gcnew array<Byte>(bufferSize);
receiveBuffer = gcnew array<Byte>(bufferSize);
tcpServer = gcnew TcpListener(listenInterface, listenPort);
// Start listening for connections
tcpServer->Start();
incomeText = "";
connection_active = false;
readyToRead = true;
System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));
int loopRunner;
loopRunner = 0;
while(loopRunner < 15)
{
pictureBoxArrayLeft[loopRunner] = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBoxArrayLeft[loopRunner]))->BeginInit();
//
// pictureBox1
//
this->pictureBoxArrayLeft[loopRunner]->BackColor = System::Drawing::Color::Black;
this->pictureBoxArrayLeft[loopRunner]->Location = System::Drawing::Point(0, (73*loopRunner));
this->pictureBoxArrayLeft[loopRunner]->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"pictureBox1.Image")));
this->pictureBoxArrayLeft[loopRunner]->Size = System::Drawing::Size(73,73);
this->pictureBoxArrayLeft[loopRunner]->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
this->pictureBoxArrayLeft[loopRunner]->TabIndex = 1;
this->pictureBoxArrayLeft[loopRunner]->TabStop = false;
this->pictureBoxArrayLeft[loopRunner]->Visible = true;
this->Controls->Add(this->pictureBoxArrayLeft[loopRunner]);
pictureBoxArrayLeft[loopRunner]->BringToFront();
loopRunner++;
}
loopRunner = 0;
while(loopRunner < 15)
{
pictureBoxArrayRight[loopRunner] = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBoxArrayRight[loopRunner]))->BeginInit();
//
// pictureBox1
//
this->pictureBoxArrayRight[loopRunner]->BackColor = System::Drawing::Color::Black;
this->pictureBoxArrayRight[loopRunner]->Location = System::Drawing::Point((1342-73), (73*loopRunner));
this->pictureBoxArrayRight[loopRunner]->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"pictureBox1.Image")));
this->pictureBoxArrayRight[loopRunner]->Size = System::Drawing::Size(73,73);
this->pictureBoxArrayRight[loopRunner]->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
this->pictureBoxArrayRight[loopRunner]->TabIndex = 1;
this->pictureBoxArrayRight[loopRunner]->TabStop = false;
this->pictureBoxArrayRight[loopRunner]->Visible = true;
this->Controls->Add(this->pictureBoxArrayRight[loopRunner]);
pictureBoxArrayRight[loopRunner]->BringToFront();
loopRunner++;
}
}
void pictures(String^ incomeText)
{
readyToRead = false;
int counter;
for(counter = 0; counter < 15; counter++)
{
pictureBoxArrayLeft[counter]->Visible = false;
pictureBoxArrayRight[counter]->Visible = false;
}
System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));
String^ tempstring;
String^ tempstring2;
counter = 0;
pictureBox1->Image = pictureBox1->Image->FromFile(incomeText->Substring(0,incomeText->IndexOf(L"#",0)));
tempstring = incomeText->Substring(incomeText->IndexOf(L"#",0)+1);
while(tempstring != L"")
{
tempstring2 = tempstring->Substring(0,tempstring->IndexOf(L"#",0));
pictureBoxArrayLeft[counter]->Image = (cli::safe_cast<System::Drawing::Image^ >(Image::FromFile(tempstring2)));
pictureBoxArrayRight[counter]->Image = (cli::safe_cast<System::Drawing::Image^ >(Image::FromFile(tempstring2)));
pictureBoxArrayLeft[counter]->Visible = true;
pictureBoxArrayRight[counter]->Visible = true;
tempstring = tempstring->Substring(tempstring->IndexOf(L"#",0)+1);
counter++;
}
readyToRead = true;
}
void Send(String^ outgoing)
{
if(connection_active == true)
{
sendBuffer = System::Text::Encoding::ASCII->GetBytes(outgoing);
tcpStream->Write(sendBuffer,0,sendBuffer->Length);
}
}
void StartIfPending()
{
if(tcpServer->Pending())
{
// Wait for a client connection
tcpClient = tcpServer->AcceptTcpClient();
// Get the NetworkStream so we can do Read and Write on the client connection
tcpStream = tcpClient->GetStream();
connection_active = true;
IPEndPoint^ ep = safe_cast<IPEndPoint^>(tcpClient->Client->RemoteEndPoint);
}
else
{
}
}
void Service()
{
StartIfPending();
String^ incomeText = Recieve();
if(incomeText != "" && incomeText != "<<") //check for empty String^ or empty command
{
if(readyToRead == true)
{
pictures(incomeText);
}
}
}
String^ Recieve()
{
if(connection_active == true)
{
try
{
// Receive the data
if(tcpStream->DataAvailable)
{
// Read some data
count = tcpStream->Read(receiveBuffer, 0, 4096);//nextReadCount);
// Display what we read
String^ inBufferString = System::Text::Encoding::ASCII->GetString(receiveBuffer, 0, count);
return inBufferString;
}
else
{
return "";
}
}
catch (SocketException^ err)
{
// Exceptions on the TcpListener are caught here
}
catch (IO::IOException^ err)
{
// Exceptions on the NetworkStream are caught here
}
}
else
{
return "";
}
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: array<System::Windows::Forms::PictureBox^>^ pictureBoxArrayLeft;
private: array<System::Windows::Forms::PictureBox^>^ pictureBoxArrayRight;
private: TcpListener^ tcpServer;
private: TcpClient^ tcpClient;
private: NetworkStream^ tcpStream;
private: array<Byte>^ sendBuffer;
private: array<Byte>^ receiveBuffer;
private: array<Byte>^ byteCount;
private: int count;
private: bool connection_active;
private: String^ incomeText;
private: bool readyToRead;
private: System::Windows::Forms::Timer^ timer1;
private: System::Windows::Forms::PictureBox^ pictureBox1;
private: System::ComponentModel::IContainer^ components;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid));
this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->BeginInit();
this->SuspendLayout();
//
// timer1
//
this->timer1->Enabled = true;
this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
//
// pictureBox1
//
this->pictureBox1->BackColor = System::Drawing::Color::Black;
this->pictureBox1->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"pictureBox1.Image")));
this->pictureBox1->Location = System::Drawing::Point(2, -1);
this->pictureBox1->Name = L"pictureBox1";
this->pictureBox1->Size = System::Drawing::Size(1342, 730);
this->pictureBox1->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
this->pictureBox1->TabIndex = 1;
this->pictureBox1->TabStop = false;
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(1344, 730);
this->Controls->Add(this->pictureBox1);
this->Name = L"Form1";
this->Text = L"Form1";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->EndInit();
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
Service();
}
};
}
Upvotes: 2
Views: 1849
Reputation: 941873
The C++/CLI designers pained themselves a great deal to try to rescue the RAII pattern in C++. Not terribly successfully, hard problem to solve in a managed language. They did so by encapsulating the IDisposable interface in the language itself. And completely hiding it as well, you'll get a compile error when you try to use it. The delete operator for a managed object calls the IDisposable::Dispose() method, if the class object implements it. The ~destructor of a ref class implements the Dispose() method, the GC::SuppressFinalize() call is auto-generated. The !finalizer is the one that runs when the object is actually destroyed whenever the garbage collector gets to it.
The proper incantation for the assignment to the Image property should look like this:
delete pictureBox1->Image; // Dispose the existing bitmap, if any
pictureBox1->Image = pictureBox1->Image->FromFile(...);
And if you want to clear the image then you should write it like this:
delete pictureBox1->Image;
pictureBox1->Image = nullptr;
Upvotes: 1
Reputation: 27864
In C++/CLI, you don't call Dispose explicitly. Instead, do a delete
on the object, like you would for any C++ object. The compiler turns that in a call to Dispose behind the scenes.
Upvotes: 2