【问题标题】:Implement Dispose to my method对我的方法实施 Dispose
【发布时间】:2013-05-14 16:08:02
【问题描述】:

我有一个使用 Pcapdot.Net DLL 并播放 Pcap 文件的 Winform 应用程序。 当我在循环中播放文件时,我可以看到应用程序内存被提升,直到发生崩溃,并且在堆栈跟踪中我可以看到这发生在播放文件的方法中。 所以我正在考虑添加 dispose 方法,看看它是否可以解决这个崩溃。

所以我在我的班级中添加了一个变量private bool _disposed;

和方法:

public void Dispose()
{
    Dispose(true);
}

private virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {

        }

        _disposed = true;
    }
}

我的玩法:

public bool sendBuffer(PacketDevice packetDevice)
        {
            int count = 0;
            bool bContinuePlay = true;
            PacketDevice selectedOutputDevice = packetDevice;
            _shouldContinue = true;
            _isStop = true;
            _stopButton = true;

            OfflinePacketDevice selectedInputDevice = new OfflinePacketDevice(_filePath.FullName); //open the capture file
            DateTime time = DateTime.Now;
            double totalTime = 0;
            double totalDelayTime = 0;
            double deletaTime = 0;

            using (inputCommunicator = selectedInputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
            {
                using (OutputCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000))
                {
                    ThreadStart tStarter = delegate { openAdapterForStatistics(selectedOutputDevice); };
                    Thread thread = new Thread(tStarter);
                    thread.IsBackground = true;
                    thread.Start();

                    DateTime lastTime = DateTime.MinValue;
                    double delayTime = 0;
                    Packet packet;
                    IEnumerable<Packet> packets;

                    while (inputCommunicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok && _isStop) //fill the buffer with the packets from the file
                    {
                        if (count < _numberOfPacketsInfile)
                        {
                            using (PacketSendBuffer mSendBuffer = new PacketSendBuffer((uint)packet.Length * 4))
                            {
                                if (_isBurst)
                                {
                                    if (lastTime != DateTime.MinValue)
                                    {
                                        if (packet != null)
                                        {
                                            delayTime = (packet.Timestamp.Subtract(lastTime).TotalMilliseconds) / _playSpeed; //delay between packets
                                        }

                                        if (delayTime > 1000)
                                        {
                                            if (_startTimer != null)
                                            {
                                                _startTimer(delayTime, EventArgs.Empty);
                                            }

                                            _delayForNextPacket = delayTime;
                                        }

                                        totalDelayTime += delayTime;
                                        delayTime = delayTime - deletaTime;

                                        if (delayTime < 0)
                                        {
                                            delayTime = 0;
                                        }

                                        if (evePacketProgress != null)
                                        {
                                            int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
                                            evePacketProgress(packetProgressPrecentage);
                                        }

                                        _mrEvent.WaitOne((int)delayTime);

                                        if (_stopTimer != null)
                                        {
                                            _stopTimer(delayTime, EventArgs.Empty);
                                        }
                                    } //end if
                                } // end if _brust                                                                                           

                                if (_fragmentation)
                                {
                                    foreach (Packet item in splitPacket(packet, 1))
                                    {
                                        mSendBuffer.Enqueue(item);
                                    }
                                }
                                else if (packet != null)
                                {
                                    lastTime = packet.Timestamp;
                                    mSendBuffer.Enqueue(packet);
                                }

                                if (evePacketProgress != null)
                                {
                                    int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
                                    evePacketProgress(packetProgressPrecentage);
                                }

                                try
                                {
                                    OutputCommunicator.Transmit(mSendBuffer, _isBurst); //send the packet
                                    _numberOfSendPackets++;
                                }
                                catch (Exception)
                                {

                                }
                            }///

                            totalTime = DateTime.Now.Subtract(time).TotalMilliseconds;
                            deletaTime = totalTime - totalDelayTime;
                            count++;
                        }
                    } //end while
                }
            }

            return bContinuePlay;
        }

崩溃发生在DateTime lastTime = DateTime.MinValue;这一行

我是一名新开发人员,不知道如何从这里开始。 欢迎任何帮助

【问题讨论】:

  • 大概需要看那个播放代码,猜猜是哪里出错了
  • 您能否展示您如何创建文件并在循环中使用它。也许您应该或可以将新文件的实例包装在 using(){} 语句中,该语句将处理你很难在没有看到你正在使用的当前代码的情况下推荐一些东西
  • 这个问题可能是因为你循环播放文件而不关闭它,所以文件留在内存中,多个副本达到内存限制。你能发布你的循环吗?
  • @Brad M - 如果确实有一个没有提及或显示的终结器,它肯定只是缺少suppressFinalize?
  • 查看我的更新,我也从 BackgroundWorker 调用此函数

标签: c# winforms


【解决方案1】:

Dispose 方法用于释放非托管资源,即“.NET World”中不存在的资源,例如 TCP 或数据库连接。

当 CLR 发现您的程序内存不足时,它会自动调用垃圾收集器,以释放您不再使用的对象。

只有在必须释放非托管资源时才需要实现 IDisposable。有关实现 IDisposable 的详细信息,您可以在网上找到很多文章。例如,您忘记了实现您的类终结器。

所以,如果问题出在播放文件的方法上,首先要找到导致内存增加,不能被GC释放的原因。

我不知道 Pcapdot.Net,但是尝试找到一种方法来释放正在播放的文件,或者类似的东西。可能不需要实现 IDisposable,只需添加对该方法的调用即可。

【讨论】:

  • 这并不完全正确。即使您的对象不直接操作非 .NET 资源,您也应该对也使用其他实现 IDisposable 的对象的对象实现 dispose。通过确保确定性地删除对它们的引用,允许垃圾收集器收集它们,它对于控制需要大量内存的 .NET 对象的生命周期也很有用。
  • 小心——确实,Dispose 通常用于清理非托管资源,但也用于“确定性释放”托管资源,如展开事件处理程序、关闭服务、释放锁等
  • -1:这里有几个问题。 1) 如果您的类包含IDisposable 的字段,您可能需要实现IDisposable,即使您的类不直接拥有非托管资源。 2) 如果你发现自己在 C# 中编写了一个终结器,那么你可能做错了什么。情况并非总是,但您的直觉应该是认真质疑为什么要添加它并寻找删除它的方法(例如,改用SafeHandle)。
  • 没错,我忘记了这些试图简化答案的案例,但如果程序员忘记了这一点,则必须实现终结器以强制调用 Dispose。这个link 说明了这一点。
  • 崩溃发生在DateTime lastTime = DateTime.MinValue;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2022-07-16
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多