GVKun编程网logo

MailBee.NET Objects退回邮件教程(二):POP3部分(邮件系统退回)

26

在本文中,您将会了解到关于MailBee.NETObjects退回邮件教程的新资讯,同时我们还将为您解释二:POP3部分的相关在本文中,我们将带你探索MailBee.NETObjects退回邮件教程的

在本文中,您将会了解到关于MailBee.NET Objects退回邮件教程的新资讯,同时我们还将为您解释二:POP3部分的相关在本文中,我们将带你探索MailBee.NET Objects退回邮件教程的奥秘,分析二:POP3部分的特点,并给出一些关于.NET Core 3.0之深入源码理解ObjectPool(二)、ASP.NET Core 中的 ObjectPool 对象重用(二)、Block will be retained by an object strongly retained by the captured object、com.badlogic.gdx.maps.objects.PolylineMapObject的实例源码的实用技巧。

本文目录一览:

MailBee.NET Objects退回邮件教程(二):POP3部分(邮件系统退回)

MailBee.NET Objects退回邮件教程(二):POP3部分(邮件系统退回)

MailBee.NET Objects是一款为创建、发送、接收以及处理电子邮件而设计的健壮、功能丰富的.NET控件。几行代码便可为应用程序添加E-Mail支持,

简单高效。具备“必需”以及独特的功能,这些控件帮助开发人员简单快速地将复杂的电子邮件功能添加到他们的应用程序中。


MailBee.NET Objects介绍和试用点击查看>>>


本文主要介绍了SMTP服务器退回邮件的代码示例。目前MailBee.NET Objects在线订购享75折优惠正在进行中,欢迎您下载试用版进行运用!

在上期的SMTP部分中,我们将退回的电子邮件发送到指定的单个电子邮件地址。

每封退回的电子邮件都包含失败的电子邮件地址(以及其他信息)。这个失败的地址是我们想知道的。这个任务看起来很简单 - 你需要做的是扫描退回的

邮件以确定地址的典型字段。但是有一个隐藏的危险:每个邮件服务器都有自己的邮件退回格式。虽然它们几乎具有相同的“From”和“主题”字段,但是退回地址可以在邮件的任何位置。MailEnable服务器的典型退回邮件如下所示:

From: POSTMASTER@domain.com
To: jdoe@domain.com
Subject: Message Delivery Failure

MailEnable: Message Delivery Failure.

The following recipient(s) could not be reached: 

Recipient: [SMTP: bill@domain.com] Reason: The message could not be delivered because the domain name (domain.com) does not appear 

to be registered.


函数GetInvalidEmailAddressME()检查邮件是否被退回,并从退回的邮件中提取失败的地址。由于退回邮件格式不同,此功能仅对MailEnable服务器有效。例如,如果你正在使用Communigate Pro服务器,则退回消息如下所示:

From: MAILER-DAEMON@domain.local
To: jdoe@localhost Subject:
Undeliverable mail:

Failed to deliver to ''''

 

正如你所看到的,这个退回的邮件与前一个几乎相同。使用哪个服务器并不重要,退回信息总是有From,To和Subject字段,退回信息在其正文中有失败的地址。函数GetInvalidEmailAddressCP()与前一个函数几乎相同; 区别仅在于检查邮件字段并搜索失败的地址。支持尽可能多的退回电子邮件格式至关重要。这就是为什么你需要修改GetInvalidEmailAddress()函数,以适应服务器使用的退回电子邮件格式。

 

注意:在某些情况下,你可能需要扫描退回的电子邮件以获取其他信息。如果由于暂时的问题,退回的邮件到达,则不要删除电子邮件地址:邮箱超过配

额,邮件服务器关闭等。退回邮件可以分为两种类型:硬邮件和软邮件。如果是不存在的帐户或域,则会发生硬性退回。其他故障,如完整的邮箱或暂时

不可用的域,则是软性退回。你可以为数据库中的每个地址进行计算。也许下一次尝试发送邮件到具有一些软性退回的地址时将成功。

 

代码示例:

在此示例中,我们从指定的帐户中检索退回的电子邮件,然后从每个退回的电子邮件中提取失败的电子邮件地址。失败的地址传递给RemoveEmailFromDatabase子程序,该子程序必须从数据库中删除失败的地址。应用程序还会从服务器中删除退回的电子邮件,以避免下次处理。

C#:

// Create POP3 object
Pop3 pop = new Pop3();

// Enable logging to file
pop.Log.Enabled = true;
pop.Log.Filename = @"C:\log.txt";
pop.Log.Clear();

// Connect to POP3 server
pop.Connect("mail.domain.com");
pop.Login("bounce", "secret");

// Download headers and bodies of all messages.
MailMessageCollection msgs = pop.DownloadMessageHeaders(1, -1, -1);
                        
// Loop through all messages in the mailbox
foreach (MailMessage msg in msgs)
{
        string strLine = msg.BodyPlainText;
        Console.WriteLine("From: " + msg.From.Email);
                                
        // Get failed email address
        string str_invalid_email =  GetInvalidEmailAddressME(msg);

        // If str_invalid_email is non-empty then failed email 
        // address was found
        if (str_invalid_email.Length > 0)
        {
                // Remove failed email from database
                RemoveEmailFromDatabase(str_invalid_email);

                // Display invalid adress
                Console.WriteLine("Invalid email: " + str_invalid_email);                

                // Delete bounced email from server to avoid
                // processing it next time
                pop.DeleteMessage(msg.IndexOnServer);
        }
}

// Disconnect from POP3 server
pop.Disconnect();

// The function checks whether the message is bounced and extracts 
// failed address 
// from bounced message. Valid only for MailEnable servers
static string  GetInvalidEmailAddressME(MailMessage msg)
{
        string str_invalid_email = msg.BodyPlainText;

        // Check if this is a bounced message report
        if (msg.Subject.IndexOf("Delivery Failure") == -1)
{ 
                return "";
        }
        if (msg.From.ToString().IndexOf("POSTMASTER") == -1)
        {
                return "";
        }

        // Now we''re sure this is a bounced message report
        int i_start;
        i_start = str_invalid_email.IndexOf("SMTP:");

        // Check if bounced message report contains "Recipient:" field
        if (i_start == -1)
        {
                return "";
        }
                        
        // Get failed address
        i_start += 5;
        i_end = str_invalid_email.IndexOf("]",i_start);
        str_invalid_email.Substring(i_start, i_end);
                        
        return str_invalid_email;
}

// The function checks whether the message is bounced and extracts 
// failed address 
// from bounced message. Valid only for Communigate Pro servers
static string  GetInvalidEmailAddressCP(MailMessage msg)
{
string str_invalid_email = msg.BodyPlainText;

        // Check if this is a bounced message report
        if (msg.Subject.IndexOf("Undeliverable mail") == -1) 
        {
                return "";
        }
        if (msg.From.ToString().IndexOf("MAILER-DAEMON") == -1) 
        {
                return "";
        }

        // Now we''re sure this is a bounced message report
        int i_start;
        i_start = str_invalid_email.IndexOf("to ''<");

        // Check if bounced message report contains 
        // "Failed to deliver to " field
        if (i_start == -1)
        { 
                return "";
        }
                        
        // Get failed address
        i_start += 5;
        i_end = str_invalid_email.IndexOf("]",i_start);
        str_invalid_email.Substring(i_start, i_end);
                        
        return str_invalid_email;
}

// This function must remove (or disable) specified
// email address from mailing list
static void RemoveEmailFromDatabase(string str_invalid_email)
{
// TODO: Add your code here                        
}

 

VB.NET:

Dim pop As New Pop3

'' Enable logging to file
pop.Log.Enabled = True
pop.Log.Filename = "C:\log.txt"
pop.Log.Clear()

'' Connect to POP3 server
pop.Connect("mail.domain.com")
pop.Login("jdoe", "secret")

'' Download headers and bodies for all messages.
Dim msgs As MailMessageCollection = pop.DownloadMessageHeaders(1, -1, -1)

'' Loop through all messages in the mailbox
Dim msg As MailMessage
For Each msg In msgs
        Dim strLine As String = msg.BodyPlainText
        Console.WriteLine("From: " + msg.From.Email)

        '' Get failed email address
        Dim str_invalid_email As String = GetInvalidEmailAddressME(msg)

        '' If str_invalid_email is non-empty then failed email 
        '' address was found
        If str_invalid_email.Length > 0 Then
                ''Remove failed email from database
                RemoveEmailFromDatabase(str_invalid_email)

                '' Display invalid address
                Console.WriteLine("Invalid email: " & str_invalid_email)

                '' Delete bounced email from server to avoid
                '' processing it next time
                pop.DeleteMessage(msg.IndexOnServer)
        End If
Next
Console.ReadLine()

'' Disconnect from POP3 server
pop.Disconnect()

'' The function checks whether the message is bounced and extracts 
'' failed address 
'' from bounced message. Valid only for MailEnable servers
Function GetInvalidEmailAddressME(ByVal msg As MailMessage) As String
        Dim str_invalid_email As String = msg.BodyPlainText

        '' Check if this is a bounced message report
        If msg.Subject.IndexOf("Delivery Failure") = -1 Then
                Return ""
        End If
        If msg.From.ToString().IndexOf("POSTMASTER") = -1 Then
                Return ""
        End If

        '' Now we''re sure this is a bounced message report
        Dim i_start As Integer, i_end As Integer
        i_start = str_invalid_email.IndexOf("SMTP:")

        '' Check if bounced message report contains "Recipient:" field
        If i_start = -1 Then
                Return ""
        End If

        '' Get failed address
        i_start += 5
        i_end = str_invalid_email.IndexOf("]", i_start)
        str_invalid_email.Substring(i_start, i_end)

        Return str_invalid_email
End Function

'' The function checks whether the message is bounced and extracts 
'' failed address 
'' from bounced message. Valid only for Communigate Pro servers
Function GetInvalidEmailAddressCP(ByVal msg As MailMessage) As String
        Dim str_invalid_email As String = msg.BodyPlainText

        '' Check if this is a bounced message report
        If msg.Subject.IndexOf("Undeliverable mail") = -1 Then
                Return ""
        End If
        If msg.From.ToString().IndexOf("MAILER-DAEMON") = -1 Then
                Return ""
        End If

        '' Now we''re sure this is a bounced message report
        Dim i_start As Integer, i_end As Integer
        i_start = str_invalid_email.IndexOf("to ''<")

        '' Check if bounced message report contains 
        '' "Failed to deliver to " field
        If i_start = -1 Then
                Return ""
        End If

        '' Get failed address
        i_start += 5
        i_end = str_invalid_email.IndexOf("]", i_start)
        str_invalid_email.Substring(i_start, i_end)

        Return str_invalid_email
End Function

'' This function must remove (or disable) specified
'' email address from mailing list
Sub RemoveEmailFromDatabase(ByVal str_invalid_email As String)
        '' TODO: Add your code here                        
End Sub

.NET Core 3.0之深入源码理解ObjectPool(二)

.NET Core 3.0之深入源码理解ObjectPool(二)

写在前面

前文主要介绍了ObjectPool的一些理论基础,本文主要从源码角度理解Microsoft.Extensions.ObjectPool是如何实现的。下图为其三大核心组件图:

objectpool2

核心组件

ObjectPool

ObjectPool是一个泛型抽象类,里面只有两个抽象方法,Get和Return。它从底层定义了最一般的接口。

  • Get方法用于从对象池获取到可用对象,如果对象不可用则创建对象并返回出来
  • Return方法用户将对象返回到对象池

源码如下:

   1:  public abstract class ObjectPool<T> where T : class
   2:  {
   3:      /// <summary>
   4:      /// Gets an object from the pool if one is available, otherwise creates one.
   5:      /// </summary>
   6:      /// <returns>A <typeparamref name="T"/>.</returns>
   7:      public abstract T Get();
   8:   
   9:      /// <summary>
  10:      /// Return an object to the pool.
  11:      /// </summary>
  12:      /// <param name="obj">The object to add to the pool.</param>
  13:      public abstract void Return(T obj);
  14:  }

ObjectPoolProvider

ObjectPoolProvider也是抽象类,其内部内置了一个已经实现的Create泛型方法以及一个抽象Create方法,这代表两种ObjectPool的创建方式,一个是基于默认策略的,一个是基于用户自定义策略的。

   1:  public abstract class ObjectPoolProvider
   2:  {
   3:      /// <summary>
   4:      /// Creates an <see cref="ObjectPool"/>.
   5:      /// </summary>
   6:      /// <typeparam name="T">The type to create a pool for.</typeparam>
   7:      public ObjectPool<T> Create<T>() where T : class, new()
   8:      {
   9:          return Create<T>(new DefaultPooledObjectPolicy<T>());
  10:      }
  11:   
  12:      /// <summary>
  13:      /// Creates an <see cref="ObjectPool"/> with the given <see cref="IPooledObjectPolicy{T}"/>.
  14:      /// </summary>
  15:      /// <typeparam name="T">The type to create a pool for.</typeparam>
  16:      public abstract ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy) where T : class;
  17:  }

IPooledObjectPolicy

这个接口是一个泛型接口,用于提供一种策略来管理对象池中的对象,同样也有两个方法,Create和Return。

  • Create方法用于创建相关类型实例
  • Return方法用于将已经使用好的对象放回到对象池的时候进行逻辑处理,包括对象的状态重置以及是否能够放回到对象池
   1:  public interface IPooledObjectPolicy<T>
   2:  {
   3:      /// <summary>
   4:      /// Create a <typeparamref name="T"/>.
   5:      /// </summary>
   6:      /// <returns>The <typeparamref name="T"/> which was created.</returns>
   7:      T Create();
   8:   
   9:      /// <summary>
  10:      /// Runs some processing when an object was returned to the pool. Can be used to reset the state of an object and indicate if the object should be returned to the pool.
  11:      /// </summary>
  12:      /// <param name="obj">The object to return to the pool.</param>
  13:      /// <returns><code>true</code> if the object should be returned to the pool. <code>false</code> if it''s not possible/desirable for the pool to keep the object.</returns>
  14:      bool Return(T obj);
  15:  }

该接口有一个实现PooledObjectPolicy,这是一个抽象类,内部有两个抽象方法:

   1:  public abstract class PooledObjectPolicy<T> : IPooledObjectPolicy<T>
   2:  {
   3:      public abstract T Create();
   4:   
   5:      public abstract bool Return(T obj);
   6:  }

实现机制

其内部实现逻辑较为简单,充分考虑到了一般实现、对象追踪、对象释放等场景的使用方式。

以下为其逻辑图:
objectpool3

DefaultObjectPool

DefaultObjectPool实现了ObjectPool,其内部维护了一个结构体类型的私有数组,用于存储相关对象。该数组的大小在构造函数中定义,其实际大小为输入值减去1(默认情况下,其值为逻辑处理器数量的两倍)主要是因为DefaultObjectPool单独将首项定义了出来。

以下为DefaultObjectPool中Get和Return的实现:

   1:  public override T Get()
   2:  {
   3:      var item = _firstItem;
   4:      if (item == null || Interlocked.CompareExchange(ref _firstItem, null, item) != item)
   5:      {
   6:          var items = _items;
   7:          for (var i = 0; i < items.Length; i++)
   8:          {
   9:              item = items[i].Element;
  10:              if (item != null && Interlocked.CompareExchange(ref items[i].Element, null, item) == item)
  11:              {
  12:                  return item;
  13:              }
  14:          }
  15:   
  16:          item = Create();
  17:      }
  18:   
  19:      return item;
  20:  }
  21:   
  22:  public override void Return(T obj)
  23:  {
  24:      if (_isDefaultPolicy || (_fastPolicy?.Return(obj) ?? _policy.Return(obj)))
  25:      {
  26:          if (_firstItem != null || Interlocked.CompareExchange(ref _firstItem, obj, null) != null)
  27:          {
  28:              var items = _items;
  29:              for (var i = 0; i < items.Length && Interlocked.CompareExchange(ref items[i].Element, obj, null) != null; ++i)
  30:              {
  31:              }
  32:          }
  33:      }
  34:  }

通过源码可以知道这两个方法大量使用了Interlocked.CompareExchange:

   1:  public static int CompareExchange(
   2:      ref int location1,
   3:      int value,
   4:      int comparand
   5:  )

比较location1与comparand,如果不相等,什么都不做;如果location1与comparand相等,则用value替换location1的值。无论比较结果相等与否,返回值都是location1中原有的值。

Interlocked.CompareExchange的使用确保了线程安全性。

DefaultObjectPoolProvider

DefaultObjectPoolProvider实现了ObjectPoolProvider,该类重写了Create方法并返回ObjectPool对象。该类还定义了MaximumRetained属性,默认情况下,其值为逻辑处理器数量的两倍。

其源码如下,比较简单:

   1:  public class DefaultObjectPoolProvider : ObjectPoolProvider
   2:  {
   3:      /// <summary>
   4:      /// The maximum number of objects to retain in the pool.
   5:      /// </summary>
   6:      public int MaximumRetained { get; set; } = Environment.ProcessorCount * 2;
   7:   
   8:      /// <inheritdoc/>
   9:      public override ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy)
  10:      {
  11:          if (policy == null)
  12:          {
  13:              throw new ArgumentNullException(nameof(policy));
  14:          }
  15:   
  16:          if (typeof(IDisposable).IsAssignableFrom(typeof(T)))
  17:          {
  18:              return new DisposableObjectPool<T>(policy, MaximumRetained);
  19:          }
  20:   
  21:          return new DefaultObjectPool<T>(policy, MaximumRetained);
  22:      }
  23:  }

其中DisposableObjectPool是DefaultObjectPool类的派生类,这个类也实现了IDisposable,用于创建可手动释放的ObjectPool对象。

其相关代码如下:

   1:  public void Dispose()
   2:  {
   3:      _isDisposed = true;
   4:   
   5:      DisposeItem(_firstItem);
   6:      _firstItem = null;
   7:   
   8:      ObjectWrapper[] items = _items;
   9:      for (var i = 0; i < items.Length; i++)
  10:      {
  11:          DisposeItem(items[i].Element);
  12:          items[i].Element = null;
  13:      }
  14:  }
  15:   
  16:  private void DisposeItem(T item)
  17:  {
  18:      if (item is IDisposable disposable)
  19:      {
  20:          disposable.Dispose();
  21:      }
  22:  }

DefaultPooledObjectPolicy

该类继承了PooledObjectPolicy,实现也非常简单。

不过值得注意的是,PooledObjectPolicy还有一个实现StringBuilderPooledObjectPolicy,这个类从命名上看就知道是基于StringBuilder的。其内部默认定义了StringBuilder的大小以及初始化容量。并确定了超出容量后,将不允许归还对象。

在我们自定义PooledObjectPolicy的时候,可以参考这段实现去扩展新的PooledObjectPolicy对象。

我们看一下源码:

   1:  public class StringBuilderPooledObjectPolicy : PooledObjectPolicy<StringBuilder>
   2:  {
   3:      public int InitialCapacity { get; set; } = 100;
   4:   
   5:      public int MaximumRetainedCapacity { get; set; } = 4 * 1024;
   6:   
   7:      public override StringBuilder Create()
   8:      {
   9:          return new StringBuilder(InitialCapacity);
  10:      }
  11:   
  12:      public override bool Return(StringBuilder obj)
  13:      {
  14:          if (obj.Capacity > MaximumRetainedCapacity)
  15:          {
  16:              // Too big. Discard this one.
  17:              return false;
  18:          }
  19:   
  20:          obj.Clear();
  21:          return true;
  22:      }
  23:  }

对象追踪

该库内部定义了LeakTrackingObjectPool和LeakTrackingObjectPoolProvider用于追踪对象状态。

  • LeakTrackingObjectPoolProvider会根据构造函数传入的ObjectPoolProvider类型对象,创建LeakTrackingObjectPool实例。
  • LeakTrackingObjectPool内部定义了ConditionalWeakTable<T, Tracker>类型的数组,MSDN的解释是使编译器可以将对象字段动态附加到托管对象,这个对象会自动维护内部的键值对,而不会一直使其停留在内存中。

Tracker是LeakTrackingObjectPool的内部类,其目的是为了方便我们对对象本身进行维护跟踪,其定义如下:

   1:  private class Tracker : IDisposable
   2:  {
   3:      private readonly string _stack;
   4:      private bool _disposed;
   5:   
   6:      public Tracker()
   7:      {
   8:          _stack = Environment.StackTrace;
   9:      }
  10:   
  11:      public void Dispose()
  12:      {
  13:          _disposed = true;
  14:          GC.SuppressFinalize(this);
  15:      }
  16:   
  17:      ~Tracker()
  18:      {
  19:          if (!_disposed && !Environment.HasShutdownStarted)
  20:          {
  21:              Debug.Fail($"{typeof(T).Name} was leaked. Created at: {Environment.NewLine}{_stack}");
  22:          }
  23:      }
  24:  }

原文出处:https://www.cnblogs.com/edison0621/p/11747912.html

ASP.NET Core 中的 ObjectPool 对象重用(二)

ASP.NET Core 中的 ObjectPool 对象重用(二)

前言

上一篇文章主要介绍了 ObjectPool 的理论知识,再来介绍一下 Microsoft.Extensions.ObjectPool 是如何实现的.

image

核心组件

ObjectPool

ObjectPool 是一个泛型抽象接口,他抽象了两个方法 Get 和 Return

  • Get 方法用于从对象池获取到可用对象,如果对象不可用则创建对象并返回出来
  • Return 方法用户将对象返回到对象池

    /// <summary>
    /// A pool of objects.
    /// </summary>
    /// <typeparam name="T">The type of objects to pool.</typeparam>
    public abstract class ObjectPool<T> where T : class
    {
        /// <summary>
        /// Gets an object from the pool if one is available, otherwise creates one.
        /// </summary>
        /// <returns>A <typeparamref name="T"/>.</returns>
        public abstract T Get();

        /// <summary>
        /// Return an object to the pool.
        /// </summary>
        /// <param name="obj">The object to add to the pool.</param>
        public abstract void Return(T obj);
    }


ObjectPoolProvider

ObjectPoolProvider 是一个抽象接口他内置了 Create 的泛型方法和 Create 的泛型抽象方法,他是一个基于默认策略的。


    /// <summary>
    /// A provider of <see cref="ObjectPool{T}"/> instances.
    /// </summary>
    public abstract class ObjectPoolProvider
    {
        /// <summary>
        /// Creates an <see cref="ObjectPool"/>.
        /// </summary>
        /// <typeparam name="T">The type to create a pool for.</typeparam>
        public ObjectPool<T> Create<T>() where T : class, new()
        {
            return Create<T>(new DefaultPooledObjectPolicy<T>());
        }

        /// <summary>
        /// Creates an <see cref="ObjectPool"/> with the given <see cref="IPooledObjectPolicy{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type to create a pool for.</typeparam>
        public abstract ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy) where T : class;
    }
    

IPooledObjectPolicy

IPooledObjectPolicy 是一个泛型接口,提供策略管理对象池,该类也定义了两个方法 CreateReturn 以提供策略实现

  • Create 用于创建相关的类实例
  • Return 用于将已经使用完的对象放回到池中,包括重置对象状态以及是否能够放回到池中

    /// <summary>
    /// Represents a policy for managing pooled objects.
    /// </summary>
    /// <typeparam name="T">The type of object which is being pooled.</typeparam>
    public interface IPooledObjectPolicy<T>
    {
        /// <summary>
        /// Create a <typeparamref name="T"/>.
        /// </summary>
        /// <returns>The <typeparamref name="T"/> which was created.</returns>
        T Create();

        /// <summary>
        /// Runs some processing when an object was returned to the pool. Can be used to reset the state of an object and indicate if the object should be returned to the pool.
        /// </summary>
        /// <param name="obj">The object to return to the pool.</param>
        /// <returns><code>true</code> if the object should be returned to the pool. <code>false</code> if it''s not possible/desirable for the pool to keep the object.</returns>
        bool Return(T obj);
    }

PooledObjectPolicy 是一个泛型抽象类,并且实现了 IPooledObjectPolicy,对外提供了两个抽象方法


    public abstract class PooledObjectPolicy<T> : IPooledObjectPolicy<T>
    {
        public abstract T Create();

        public abstract bool Return(T obj);
    }

实现机制

DefaultObjectPool

DefaultObjectPool 实现了 ObjectPool,Interlocked.CompareExchange (ref _firstItem, null, item) 将_firstItem 的值和 item 的值比较,相等则用 null 替换_firstItem,否则不操作,不管替换还是不替换返回的都是原来保存在_firstItem 的值。

Interlocked 可以为多个线程共享的变量提供原子操作。

  • Interlocked.Increment:以原子操作的形式递增指定变量的值并存储结果。
  • Interlocked.Decrement 以原子操作的形式递减指定变量的值并存储结果。
  • Interlocked.Add 以原子操作的形式,添加两个整数并用两者的和替换第一个整数
        public override T Get()
        {
            var item = _firstItem;
            if (item == null || Interlocked.CompareExchange(ref _firstItem, null, item) != item)
            {
                var items = _items;
                for (var i = 0; i < items.Length; i++)
                {
                    item = items[i].Element;
                    if (item != null && Interlocked.CompareExchange(ref items[i].Element, null, item) == item)
                    {
                        return item;
                    }
                }

                item = Create();
            }

            return item;
        }

        public override void Return(T obj)
        {
            if (_isDefaultPolicy || (_fastPolicy?.Return(obj) ?? _policy.Return(obj)))
            {
                if (_firstItem != null || Interlocked.CompareExchange(ref _firstItem, obj, null) != null)
                {
                    var items = _items;
                    for (var i = 0; i < items.Length && Interlocked.CompareExchange(ref items[i].Element, obj, null) != null; ++i)
                    {
                    }
                }
            }
        }

DefaultObjectPoolProvider

DefaultObjectPoolProvider 重写了 ObjectPoolProvider 中 Crearte 方法, 设置了默认的对象最大数量只能用的是默认的 Environment.ProcessorCount * 2 (CPU 处理器的两倍)


    /// <summary>
    /// The default <see cref="ObjectPoolProvider"/>.
    /// </summary>
    public class DefaultObjectPoolProvider : ObjectPoolProvider
    {
        /// <summary>
        /// The maximum number of objects to retain in the pool.
        /// </summary>
        public int MaximumRetained { get; set; } = Environment.ProcessorCount * 2;

        /// <inheritdoc/>
        public override ObjectPool<T> Create<T>(IPooledObjectPolicy<T> policy)
        {
            if (policy == null)
            {
                throw new ArgumentNullException(nameof(policy));
            }

            if (typeof(IDisposable).IsAssignableFrom(typeof(T)))
            {
                return new DisposableObjectPool<T>(policy, MaximumRetained);
            }

            return new DefaultObjectPool<T>(policy, MaximumRetained);
        }
    }


DisposableObjectPool

DisposableObjectPool 继承了 DefaultObjectPool 以及实现了 IDisposable 用于手动的回收对象


      public void Dispose()
        {
            _isDisposed = true;

            DisposeItem(_firstItem);
            _firstItem = null;

            ObjectWrapper[] items = _items;
            for (var i = 0; i < items.Length; i++)
            {
                DisposeItem(items[i].Element);
                items[i].Element = null;
            }
        }

        private void DisposeItem(T item)
        {
            if (item is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }


LeakTrackingObjectPool

LeakTrackingObjectPool 实现了 ObjectPool,它定义了 ConditionalWeakTable 他是一个弱引用字典,ConditionalWeakTable<TKey,TValue> 中的所有 Key 和所有的 Value 都是弱引用的,并且会在其 Key 被回收或者 Key 和 Value 都被回收之后自动从集合中消失。这意味着当你使用它来为一个类型附加一些字段或者属性的时候完全不用担心内存泄漏的问题


    public class LeakTrackingObjectPool<T> : ObjectPool<T> where T : class
    {
        private readonly ConditionalWeakTable<T, Tracker> _trackers = new ConditionalWeakTable<T, Tracker>();
        private readonly ObjectPool<T> _inner;

        public LeakTrackingObjectPool(ObjectPool<T> inner)
        {
            if (inner == null)
            {
                throw new ArgumentNullException(nameof(inner));
            }

            _inner = inner;
        }

        public override T Get()
        {
            var value = _inner.Get();
            _trackers.Add(value, new Tracker());
            return value;
        }

        public override void Return(T obj)
        {
            Tracker tracker;
            if (_trackers.TryGetValue(obj, out tracker))
            {
                _trackers.Remove(obj);
                tracker.Dispose();
            }

            _inner.Return(obj);
        }

        private class Tracker : IDisposable
        {
            private readonly string _stack;
            private bool _disposed;

            public Tracker()
            {
                _stack = Environment.StackTrace;
            }

            public void Dispose()
            {
                _disposed = true;
                GC.SuppressFinalize(this);
            }

            ~Tracker()
            {
                if (!_disposed && !Environment.HasShutdownStarted)
                {
                    Debug.Fail($"{typeof(T).Name} was leaked. Created at: {Environment.NewLine}{_stack}");
                }
            }
        }
    }

参考

https://blog.walterlv.com/post/conditional-weak-table.html

https://www.cnblogs.com/edison0621/p/11747912.html

原文出处:https://www.cnblogs.com/yyfh/p/11980645.html

Block will be retained by an object strongly retained by the captured object

Block will be retained by an object strongly retained by the captured object

Block will be retained by an object strongly retained by the captured object

防止iOS中私有属性在block中的循环引用

对于一般的@property修饰的属性我们可以使用__weak转换一下self来修饰

    __weak typeof(self) weakSelf = self;
    //然后把self.xxx变成weakself.xxx

那么.对于一些没有使用@property修饰的私有属性呢.比如一下这种.

    @interface xxx () {
   
   
   
        NSString *yyy;
    }
    // MARK: 1
    //Block implicitly retains ''self''; explicitly mention ''self'' to indicate this is intended behavior
    //Insert ''self->''
    self.button.didSelectBlock = ^{
   
   
   
        yyy = @"123131133";
        NSLog(@"%@",yyy);
    };

编译器让我们使用self->去修饰这个属性,
当我们换成self->的时候

    // MARK: 2
    //Block will be retained by an object strongly retained by the captured object
    self.button.didSelectBlock = ^{
   
   
   
        self->yyy = @"12313123";
        NSLog(@"%@",self->yyy);
    };

循环引用了.那么我们如果把self替换成weakSelf呢

    // MARK: 3
    // ERROR
    //Dereferencing a __weak pointer is not allowed due to possible null value caused by race condition, assign it to strong variable first
    __weak typeof(self) weakSelf = self;
        self.button.didSelectBlock = ^{
   
   
   
        weakSelf->yyy = @"12313123";
        NSLog(@"%@",weakSelf->yyy);
    };
    // MARK: 4
    __weak typeof(self) weakSelf = self;
    self.button.didSelectBlock = ^{
   
   
   
        __strong typeof(weakSelf) strongSelf = weakSelf;
        strongSelf->yyy = @"12313123";
        NSLog(@"%@",strongSelf->yyy);
    };

本文同步分享在 博客“早起的年轻人”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

com.badlogic.gdx.maps.objects.PolylineMapObject的实例源码

com.badlogic.gdx.maps.objects.PolylineMapObject的实例源码

项目:joe    文件:TiledMapLevelLoadable.java   
private void processFreeBodies(Array<MapObject> bodies) {
    for (MapObject object : bodies) {
        FixtureBodyDeFinition fixtureBodyDeFinition;
        if (object instanceof RectangleMapObject) {
            fixtureBodyDeFinition = TiledUtils.createRectangleFixtureBodyDef((RectangleMapObject)object);
        } else if (object instanceof CircleMapObject) {
            fixtureBodyDeFinition = TiledUtils.createCircleFixtureBodyDef((CircleMapObject)object);
        } else if (object instanceof EllipseMapObject) {
            fixtureBodyDeFinition = TiledUtils.createEllipseFixtureBodyDef((EllipseMapObject)object);
        } else if (object instanceof polylineMapObject || object instanceof polygonMapObject) {
            fixtureBodyDeFinition = TiledUtils.createpolyFixtureBodyDef(object);
        } else {
            throw new InvalidConfigException(filename,"UnkNown MapObject type");
        }

        freeBodyDeFinitions.add(fixtureBodyDeFinition);
    }
}
项目:joe    文件:TiledUtils.java   
public static FixtureDef getFixtureDefFromBodySkeleton(MapObject object) {
    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.density = 1;
    fixtureDef.friction = 0;
    fixtureDef.restitution = 0;

    Shape shape = null;
    if (object instanceof TextureMapObject) {
        shape = getTextureMapShape(object);
    } else if (object instanceof RectangleMapObject) {
        shape = getRectangleShape(object);
    } else if (object instanceof CircleMapObject) {
        shape = getCircleShape(object);
    } else if (object instanceof EllipseMapObject) {
        shape = getEllipseShape(object);
    } else if (object instanceof polygonMapObject) {
        shape = getpolygonShape(object);
    } else if (object instanceof polylineMapObject) {
        shape = getpolylineshape(object);
    }

    fixtureDef.shape = shape;

    return fixtureDef;
}
项目:DropTheCube-LD32    文件:Box2DUtils.java   
private static Shape getpolyline(polylineMapObject object) {
    float[] vertices = object.getpolyline().getTransformedVertices();
    Vector2[] worldVertices = new Vector2[vertices.length / 2];

    for(int i = 0; i < vertices.length / 2; ++i){
        Vector2 vector = new Vector2();
        vector.x = vertices[i * 2];
        vector.y = vertices[i * 2 + 1];

        worldVertices[i] = Pixels.toMeters(new Vector2(vector));
    }

    ChainShape shape = new ChainShape();
    shape.createChain(worldVertices);
    return shape;
}
项目:joe    文件:TiledUtils.java   
private static Shape getpolylineshape(MapObject object) {
    polyline polyline = ((polylineMapObject)object).getpolyline();
    float[] vertices = polyline.getTransformedVertices();
    for (int i = 0; i < vertices.length; i++) {
        vertices[i] *= MainCamera.getInstance().getTileMapScale();
    }

    ChainShape shape = new ChainShape();
    shape.createChain(vertices);

    return shape;
}
项目:SupaBax    文件:BodyBuilder.java   
/**
 * 
 * @param world
 * @param map
 */
public void createBodies(ArrayList<Entity> entities,World world,TiledMap map){
    MapObjects objects;

    objects = map.getLayers().get("ground").getobjects();
    for(MapObject object : objects){
        if(object instanceof RectangleMapObject){
            createRectangle(world,(RectangleMapObject) object,0.5f,0.4f,0.6f);
        } else if(object instanceof polygonMapObject){
            createpolygon(world,(polygonMapObject) object,0.6f);
        } else if(object instanceof polylineMapObject){
            createpolyline(world,(polylineMapObject) object,0.6f);
        } else if(object instanceof EllipseMapObject){
            createEllipse(world,(EllipseMapObject) object,0.6f);
        } else{
            Gdx.app.error("Error","Invalid map object");
        }
    }

    /*
    objects = map.getLayers().get("dynamic").getobjects();
    for(MapObject object : objects){
        RectangleMapObject entity = (RectangleMapObject) object;
        Rectangle position = entity.getRectangle();
        entities.add(new Box(world,new Vector2(position.x / SupaBox.PPM,position.y / SupaBox.PPM),new Vector2(0f,0f),1f,1f));
    }
    */
}
项目:SupaBax    文件:BodyBuilder.java   
/**
 * 
 * @param world
 * @param polylineObject
 * @param density
 * @param friction
 * @param restitution
 */
private void createpolyline(World world,polylineMapObject polylineObject,float density,float friction,float restitution){
    polyline polyline = polylineObject.getpolyline();
    ChainShape shape = new ChainShape();
    float[] vertices = polyline.getTransformedVertices();
    float[] worldVertices = new float[vertices.length];

    for(int i = 0; i < vertices.length; i++){
        worldVertices[i] = vertices[i] / SupaBox.PPM;
    }

    shape.createChain(worldVertices);

    BodyDef bodyDef = new BodyDef();
    bodyDef.type = BodyType.StaticBody;

    Body body = world.createBody(bodyDef);

    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.shape = shape;
    fixtureDef.density = density;
    fixtureDef.friction = friction;
    fixtureDef.restitution = restitution;

    body.createFixture(fixtureDef);

    shape.dispose();
}
项目:practicos    文件:GeneradorNivel.java   
private Shape getpolyline(polylineMapObject polylineObject) {
    float[] vertices = polylineObject.getpolyline().getTransformedVertices();
    Vector2[] worldVertices = new Vector2[vertices.length / 2];

    for (int i = 0; i < vertices.length / 2; ++i) {
        worldVertices[i] = new Vector2();
        worldVertices[i].x = vertices[i * 2] / GameWorld.units;
        worldVertices[i].y = vertices[i * 2 + 1] / GameWorld.units;
    }

    ChainShape chain = new ChainShape(); 
    chain.createChain(worldVertices);
    return chain;
}
项目:sioncore    文件:MapBodyManager.java   
private Shape getpolyline(polylineMapObject polylineObject) {
    float[] vertices = polylineObject.getpolyline().getTransformedVertices();
    Vector2[] worldVertices = new Vector2[vertices.length / 2];

    for (int i = 0; i < vertices.length / 2; ++i) {
        worldVertices[i] = new Vector2();
        worldVertices[i].x = vertices[i * 2] / units;
        worldVertices[i].y = vertices[i * 2 + 1] / units;
    }

    ChainShape chain = new ChainShape(); 
    chain.createChain(worldVertices);
    return chain;
}
项目:JavaLib    文件:MapBodyManager.java   
private Shape getpolyline(polylineMapObject polylineObject) {
    float[] vertices = polylineObject.getpolyline().getVertices(); // Changed
    Vector2[] worldVertices = new Vector2[vertices.length / 2];

    for (int i = 0; i < vertices.length / 2; ++i) {
        worldVertices[i] = new Vector2();
        worldVertices[i].x = vertices[i * 2] * m_units;
        worldVertices[i].y = vertices[i * 2 + 1] * m_units;
    }

    ChainShape chain = new ChainShape();
    chain.createChain(worldVertices);
    return chain;
}
项目:school-game    文件:WaypointNPC.java   
/**
 * Initialisiert den NPC.
 * Erstellt eine Liste aller Wegpunkte.
 */
@Override
public void onInit()
{
    super.onInit();

    float[] vertices;

    if (rawObject instanceof polylineMapObject)
    {
        polylineMapObject polyline = (polylineMapObject) rawObject;
        loop = false;

        vertices = polyline.getpolyline().getTransformedVertices();
    }
    else if (rawObject instanceof polygonMapObject)
    {
        polygonMapObject polygon = (polygonMapObject) rawObject;
        loop = true;

        vertices = polygon.getpolygon().getTransformedVertices();
    }
    else
    {
        Gdx.app.log("WARNING",objectId + ": MapObject must be polyline or polygon.");

        worldobjectManager.removeObject(this);

        return;
    }

    waypoints = new Vector2[vertices.length / 2];

    for (int i = 0; i < vertices.length / 2; i++)
    {
        waypoints[i] = new Vector2();
        waypoints[i].x = vertices[i * 2];
        waypoints[i].y = vertices[i * 2 + 1];
    }

    if (waypoints.length < 2)
    {
        Gdx.app.log("WARNING",objectId + ": Must have at least 2 Waypoints.");

        worldobjectManager.removeObject(this);

        return;
    }

    body = createCircleBody(waypoints[0].cpy(),10);
    targetIndex = 1;
}
项目:practicos    文件:GeneradorNivel.java   
private void crearColisiones() {

Array<Body> slopes = new Array<Body>();
FixtureDef fixDef = new FixtureDef();


MapObjects objects = cls.getobjects();
Iterator<MapObject> objectIt = objects.iterator();

while(objectIt.hasNext()) {
MapObject object = objectIt.next();

if (object instanceof TextureMapObject){
  continue;
}

Shape shape;
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;

if (object instanceof RectangleMapObject) {
    RectangleMapObject rectangle = (RectangleMapObject)object;
    shape = getRectangle(rectangle);
}
else if (object instanceof polygonMapObject) {
    shape = getpolygon((polygonMapObject)object);
}
else if (object instanceof polylineMapObject) {
    shape = getpolyline((polylineMapObject)object);
}
else if (object instanceof EllipseMapObject) {
    shape = getEllipse((EllipseMapObject)object);
}
else if (object instanceof CircleMapObject) {
    shape = getCircle((CircleMapObject)object);
}
else {
    continue;
}


fixDef.shape = shape;
fixDef.filter.categoryBits = GameWorld.BIT_PARED;
  fixDef.filter.maskBits = GameWorld.BIT_JUGADOR | GameWorld.BIT_ENEMIGOS | GameWorld.BIT_SENSOR;


Body suelo = GameWorld.mundo.createBody(bodyDef);
suelo.createFixture(fixDef).setUserData("cls");

slopes.add(suelo);

shape.dispose();
  }
}
项目:sioncore    文件:MapBodyManager.java   
/**
 * @param map map to be used to create the static bodies. 
 * @param layerName name of the layer that contains the shapes.
 */
public void createPhysics(Map map,String layerName) {
    MapLayer layer = map.getLayers().get(layerName);

    if (layer == null) {
        logger.error("layer " + layerName + " does not exist");
        return;
    }

    MapObjects objects = layer.getobjects();
    Iterator<MapObject> objectIt = objects.iterator();

    while(objectIt.hasNext()) {
        MapObject object = objectIt.next();

        if (object instanceof TextureMapObject){
            continue;
        }

        Shape shape;
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.StaticBody;

        if (object instanceof RectangleMapObject) {
            RectangleMapObject rectangle = (RectangleMapObject)object;
            shape = getRectangle(rectangle);
        }
        else if (object instanceof polygonMapObject) {
            shape = getpolygon((polygonMapObject)object);
        }
        else if (object instanceof polylineMapObject) {
            shape = getpolyline((polylineMapObject)object);
        }
        else if (object instanceof CircleMapObject) {
            shape = getCircle((CircleMapObject)object);
        }
        else {
            logger.error("non suported shape " + object);
            continue;
        }

        MapProperties properties = object.getProperties();
        String material = properties.get("material","default",String.class);
        FixtureDef fixtureDef = materials.get(material);

        if (fixtureDef == null) {
            logger.error("material does not exist " + material + " using default");
            fixtureDef = materials.get("default");
        }

        fixtureDef.shape = shape;
        fixtureDef.filter.categoryBits = Env.game.getCategoryBitsManager().getCategoryBits("level");

        Body body = world.createBody(bodyDef);
        body.createFixture(fixtureDef);

        bodies.add(body);

        fixtureDef.shape = null;
        shape.dispose();
    }
}

关于MailBee.NET Objects退回邮件教程二:POP3部分的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于.NET Core 3.0之深入源码理解ObjectPool(二)、ASP.NET Core 中的 ObjectPool 对象重用(二)、Block will be retained by an object strongly retained by the captured object、com.badlogic.gdx.maps.objects.PolylineMapObject的实例源码等相关内容,可以在本站寻找。

本文标签: