2

你好,我做了一个非常简单的程序,通过 TCP-IP 获取一些图片地址并将它们显示在屏幕上。我的问题是,每次我更新一张图片时都会留下记忆,这基本上让我记忆超载。

我一直在寻找一个 awnser 并得出结论,我可能需要使用函数 Dispose,我的问题是当我尝试实现它时出现以下错误

错误 C2039: 'Dispose' : is not a member of 'System::Windows::Forms::PictureBox' 请注意,我使用的是 Visual Studio 2008,它实际上对我有用。

我正在寻找的是当我想加载新图片时清除内存的正确方法。

这是我的代码,感谢那里的任何人花时间查看我的问题

    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();
             }
};
}
4

2 回答 2

2

在 C++/CLI 中,您不会显式调用 Dispose。相反,delete对对象执行 a 操作,就像对任何 C++ 对象执行的操作一样。编译器在后台调用 Dispose 将其转换。

于 2013-01-17T16:16:53.180 回答
1

C++/CLI 设计者为试图挽救 C++ 中的 RAII 模式付出了很大的努力。不是很成功,很难用托管语言解决问题。他们通过将 IDisposable 接口封装在语言本身中来做到这一点。并且完全隐藏它,当您尝试使用它时会出现编译错误。如果类对象实现它,则托管对象的删除运算符调用 IDisposable::Dispose() 方法。ref 类的 ~destructor 实现 Dispose() 方法,GC::SuppressFinalize() 调用是自动生成的。!finalizer 是在垃圾收集器到达对象时实际销毁对象时运行的对象。

分配给 Image 属性的正确咒语应如下所示:

    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;
于 2013-01-17T16:33:19.653 回答