IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> .net中的托管资源与非托管资源,如何避免内存泄露 -> 正文阅读

[大数据].net中的托管资源与非托管资源,如何避免内存泄露

托管资源与非托管资源

“非托管资源”指的是不受.net垃圾回收器控制的资源。比如打开一个数据库连接,所访问的数据库资源来源于服务器而不受.net控制。或者是客户机上其他非.net资源,资源的提供者不是通过托管代码编写的。

这就是为什么对于数据库连接,需要写在一个using中

using (var connection = new SqlConnection("connection_string_here"))
{
    connection.open();
    //..do something...
    connection.close();
}

这样using执行完后会调用连接对象的.Dispose()方法,确保所有非托管资源被清除。

以上代码等价于

var connection = new SqlConnection("connection_string_here")
try
{
    connection.open();
    //..do something...
    connection.close();
}
finally
{
if (connection != null) ((IDisposable)connection).Dispose();
}

常见的非托管资源有:文件句柄、数据流、固定内存、COM 对象、数据库连接、网络连接

这些非托管资源如果没有显式地清理他们,将会造成数据泄露和资源占用。

对于托管资源,则无需担心其何时被销毁,当一个对象实例没有被任何变量引用时,系统会自动对其进行垃圾回收

释放非托管资源方法

下面用一个例子来介绍一下.NET非托管资源回收方法

将包含非托管对象的类继承IDisposable接口,IDisposable接口要求实现Dispose方法

Stream抽象类本身也继承了IDispose接口,如果是要创建一个自定义的Stream类,则它会继承父类的所有接口,包括IDispose;在以下编写的类WrappingStream中,定义了一个Stream类型的成员m_streamBase,用于接收非托管资源,

有两个作用:

1.如果外部的传入的非托管资源已释放,WrappingStream内部的流不会释放,保证BinaryReader能够完全控制这个流。

2.由于WrappingStream继承IDispose,在使用该对象时,包在using中,当using执行完后释放内部的流时,不会导致外部的流也释放,保证外部的流供其他程序正常使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MyStreamClass
{
  /// <summary>

  /// A <see cref="Stream"/> that wraps another stream. The major feature of <see cref="WrappingStream"/> is that it does not dispose the

  /// underlying stream when it is disposed; this is useful when using classes such as <see cref="BinaryReader"/> and

  /// <see cref="System.Security.Cryptography.CryptoStream"/> that take ownership of the stream passed to their constructors.

  /// </summary>

  public class WrappingStream : Stream
  {

    /// <summary>

    /// Initializes a new instance of the <see cref="WrappingStream"/> class.

    /// </summary>

    /// <param name="streamBase">The wrapped stream.</param>

    public WrappingStream(Stream streamBase)
    {
      m_streamBase = streamBase ?? throw new ArgumentNullException("streamBase");

    }



    /// <summary>

    /// Gets a value indicating whether the current stream supports reading.

    /// </summary>

    /// <returns><c>true</c> if the stream supports reading; otherwise, <c>false</c>.</returns>

    public override bool CanRead
    {

      get { return m_streamBase == null ? false : m_streamBase.CanRead; }

    }



    /// <summary>

    /// Gets a value indicating whether the current stream supports seeking.

    /// </summary>

    /// <returns><c>true</c> if the stream supports seeking; otherwise, <c>false</c>.</returns>

    public override bool CanSeek
    {

      get { return m_streamBase == null ? false : m_streamBase.CanSeek; }

    }



    /// <summary>

    /// Gets a value indicating whether the current stream supports writing.

    /// </summary>

    /// <returns><c>true</c> if the stream supports writing; otherwise, <c>false</c>.</returns>

    public override bool CanWrite
    {

      get { return m_streamBase == null ? false : m_streamBase.CanWrite; }

    }



    /// <summary>

    /// Gets the length in bytes of the stream.

    /// </summary>

    public override long Length
    {

      get { ThrowIfDisposed(); return m_streamBase.Length; }

    }



    /// <summary>

    /// Gets or sets the position within the current stream.

    /// </summary>

    public override long Position
    {

      get { ThrowIfDisposed(); return m_streamBase.Position; }

      set { ThrowIfDisposed(); m_streamBase.Position = value; }

    }



    /// <summary>

    /// Begins an asynchronous read operation.

    /// </summary>

    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
    {

      ThrowIfDisposed();

      return m_streamBase.BeginRead(buffer, offset, count, callback, state);

    }



    /// <summary>

    /// Begins an asynchronous write operation.

    /// </summary>

    public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
    {

      ThrowIfDisposed();

      return m_streamBase.BeginWrite(buffer, offset, count, callback, state);

    }



    /// <summary>

    /// Waits for the pending asynchronous read to complete.

    /// </summary>

    public override int EndRead(IAsyncResult asyncResult)
    {

      ThrowIfDisposed();

      return m_streamBase.EndRead(asyncResult);

    }



    /// <summary>

    /// Ends an asynchronous write operation.

    /// </summary>

    public override void EndWrite(IAsyncResult asyncResult)
    {

      ThrowIfDisposed();

      m_streamBase.EndWrite(asyncResult);

    }



    /// <summary>

    /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.

    /// </summary>

    public override void Flush()
    {

      ThrowIfDisposed();

      m_streamBase.Flush();

    }



    /// <summary>

    /// Reads a sequence of bytes from the current stream and advances the position

    /// within the stream by the number of bytes read.

    /// </summary>

    public override int Read(byte[] buffer, int offset, int count)
    {

      ThrowIfDisposed();

      return m_streamBase.Read(buffer, offset, count);

    }



    /// <summary>

    /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.

    /// </summary>

    public override int ReadByte()
    {

      ThrowIfDisposed();

      return m_streamBase.ReadByte();

    }



    /// <summary>

    /// Sets the position within the current stream.

    /// </summary>

    /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>

    /// <param name="origin">A value of type <see cref="T:System.IO.SeekOrigin"/> indicating the reference point used to obtain the new position.</param>

    /// <returns>The new position within the current stream.</returns>

    public override long Seek(long offset, SeekOrigin origin)
    {

      ThrowIfDisposed();

      return m_streamBase.Seek(offset, origin);

    }



    /// <summary>

    /// Sets the length of the current stream.

    /// </summary>

    /// <param name="value">The desired length of the current stream in bytes.</param>

    public override void SetLength(long value)
    {

      ThrowIfDisposed();

      m_streamBase.SetLength(value);

    }



    /// <summary>

    /// Writes a sequence of bytes to the current stream and advances the current position

    /// within this stream by the number of bytes written.

    /// </summary>

    public override void Write(byte[] buffer, int offset, int count)
    {

      ThrowIfDisposed();

      m_streamBase.Write(buffer, offset, count);

    }



    /// <summary>

    /// Writes a byte to the current position in the stream and advances the position within the stream by one byte.

    /// </summary>

    public override void WriteByte(byte value)
    {

      ThrowIfDisposed();

      m_streamBase.WriteByte(value);

    }



    /// <summary>

    /// Gets the wrapped stream.

    /// </summary>

    /// <value>The wrapped stream.</value>

    protected Stream WrappedStream
    {

      get { return m_streamBase; }

    }



    /// <summary>

    /// Releases the unmanaged resources used by the <see cref="WrappingStream"/> and optionally releases the managed resources.

    /// </summary>

    /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>

    protected override void Dispose(bool disposing)
    {

      // doesn't close the base stream, but just prevents access to it through this WrappingStream

      if (disposing)

        m_streamBase = null;



      base.Dispose(disposing);

    }



    private void ThrowIfDisposed()
    {

      // throws an ObjectDisposedException if this object has been disposed

      if (m_streamBase == null)

        throw new ObjectDisposedException(GetType().Name);

    }



    Stream m_streamBase;
  }
}

在使用这个类时,将Stream作为一个方法传入参数传给WrapStream并实例化

private void Create(Stream streamSource)
    {
      Random rnd = new Random();
      var connections = new int[] { (int)ConnectionType.Tab, (int)ConnectionType.Blank };

      png = null;

      imageSource = null;
      var uri = new Uri(destFileName);

      //We do this to avoid memory leaks
      using (WrappingStream wrapper = new WrappingStream(streamSource))
      using (BinaryReader reader = new BinaryReader(wrapper))
      {
        imageSource = new BitmapImage();
        imageSource.BeginInit();
        imageSource.CacheOption = BitmapCacheOption.OnLoad;
        imageSource.StreamSource = reader.BaseStream; // streamSource;
        imageSource.EndInit();
        imageSource.Freeze();
      }

      imgShowImage.Source = imageSource;

      scvImage.Visibility = Visibility.Hidden;
      cnvPuzzle.Visibility = Visibility.Visible;

      var angles = new int[] { 0, 90, 180, 270 };

      int index = 0;
      for (var y = 0; y < rows; y++)
      {
        for (var x = 0; x < columns; x++)
        {
          if (x != 1000)
          {
            int upperConnection = (int)ConnectionType.None;
            int rightConnection = (int)ConnectionType.None;
            int bottomConnection = (int)ConnectionType.None;
            int leftConnection = (int)ConnectionType.None;

            if (y != 0)
              upperConnection = -1 * pieces[(y - 1) * columns + x].BottomConnection;

            if (x != columns - 1)
              rightConnection = connections[rnd.Next(2)];

            if (y != rows - 1)
              bottomConnection = connections[rnd.Next(2)];

            if (x != 0)
              leftConnection = -1 * pieces[y * columns + x - 1].RightConnection;

            int angle = 0;

            var piece = new Piece(imageSource, x, y, 0.1, 0.1, (int)upperConnection, (int)rightConnection, (int)bottomConnection, (int)leftConnection, false, index, scale);
            piece.SetValue(Canvas.ZIndexProperty, 1000 + x * rows + y);
            piece.MouseLeftButtonUp += new MouseButtonEventHandler(Piece_MouseLeftButtonUp);
            piece.MouseRightButtonUp += new MouseButtonEventHandler(Piece_MouseRightButtonUp);
            piece.Rotate(piece, angle);

            var shadowPiece = new Piece(imageSource, x, y, 0.1, 0.1, (int)upperConnection, (int)rightConnection, (int)bottomConnection, (int)leftConnection, true, shadowPieces.Count(), scale);
            shadowPiece.SetValue(Canvas.ZIndexProperty, x * rows + y);
            shadowPiece.Rotate(piece, angle);

            pieces.Add(piece);
            shadowPieces.Add(shadowPiece);
            index++;
          }
        }
      }

      var tt = new TranslateTransform() { X = 20, Y = 20 };

      foreach (var p in pieces)
      {
        Random random = new Random();
        int i = random.Next(0, pnlPickUp.Children.Count);

        p.ScaleTransform.ScaleX = 1.0;
        p.ScaleTransform.ScaleY = 1.0;
        p.RenderTransform = tt;
        p.X = -1;
        p.Y = -1;
        p.IsSelected = false;

        pnlPickUp.Children.Insert(i, p);

        double angle = angles[rnd.Next(0, 4)];
        p.Rotate(p, angle);
        shadowPieces[p.Index].Rotate(p, angle);
      }


      rectSelection.SetValue(Canvas.ZIndexProperty, 5000);

      rectSelection.StrokeDashArray = new DoubleCollection(new double[] { 4, 4, 4, 4 });
      cnvPuzzle.Children.Add(rectSelection);
    }

这是加了WrappingStream垃圾回收的效果

这是未加WrappingStream垃圾回收的效果,

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:08:39  更:2022-04-01 00:08:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:44:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码