C # Dispose () стандарт с определенной ситуацией - PullRequest
0 голосов
/ 06 октября 2019

Мы знаем, что Dispose (удаление bool) должен быть защищенным или закрытым, что если мне нужно вручную высвободить неуправляемые ресурсы? Dispose () из интерфейса IDISPOSIBLE должен вызвать Dispose (true), что означает освобождение всех ресурсов. я хочу вручную контролировать выпуск управляющих и неуправляемых ресурсов.

Официальный способ реализации Dispose - https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose. однако иногда мне нужно вручную освободить определенный ресурс с помощью Dispose (false), если эта функция будет общедоступной, или мне нужно создать другую функцию, такую ​​как DisposeUnManage () для удаления неуправляемого ресурса вручную?

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

  protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.

      }

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

public void DisposeUnmanage()
{
Dispose(false);
}

private void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.

      }

      disposed = true;
   }

как этот код из TCPStream, мне нужно использовать этот метод TCPStream.Dispose (false), когда TCP-клиент отключен. когда мой TCPServer завершает работу, я должен вызвать TCPStream.Dispose (true).

/// <summary>
        /// Closes the underlying socket
        /// </summary>
        /// <param name="disposing">
        /// If true, the EventArg objects will be disposed instead of being re-added to 
        /// the IO pool. This should NEVER be set to true unless we are shutting down the server!
        /// </param>
        private void Dispose(bool disposeEventArgs = false)
        {
            // Set that the socket is being closed once, and properly
            if (SocketClosed) return;
            SocketClosed = true;

            // If we need to dispose out EventArgs
            if (disposeEventArgs)
            {
                ReadEventArgs.Dispose();
                WriteEventArgs.Dispose();
                DisposedEventArgs = true;
            }
            else
            {
                // Finally, release this stream so we can allow a new connection
                SocketManager.Release(this);
                Released = true;
            }

            // Do a shutdown before you close the socket
            try
            {
                Connection.Shutdown(SocketShutdown.Both);
            }
            catch (Exception) { }
            finally
            {
                // Unregister for vents
                ReadEventArgs.Completed -= IOComplete;
                WriteEventArgs.Completed -= IOComplete;

                // Close the connection
                Connection.Close();
                Connection = null;
            }           

            // Call Disconnect Event
            if (!DisconnectEventCalled && OnDisconnected != null)
            {
                DisconnectEventCalled = true;
                OnDisconnected();
            }
        }

1 Ответ

0 голосов
/ 06 октября 2019

Вы явно злоупотребляете одноразовым шаблоном.

Dispose(bool disposing) должен вызываться ровно один раз, когда объект больше не нужен и никогда больше не будет использоваться. Это может быть либо потому, что кто-то напрямую вызвал Dispose() (который вызывает Dispose(true)), либо потому, что запускается финализатор объекта (который вызывает Dispose(false)). Кроме того, как отметил @Dmytro Mukalov, использование управляемых объектов во время Dispose(false) небезопасно и может привести к трудностям при отладке (но это применимо только в том случае, если ваш объект действительно имеет финализатор).

Если выпытаясь достичь пула объектов, я бы предложил вам создать, а затем внедрить сервис пулирования в этот TCPStream. Он будет управлять временем жизни объединенных объектов и разрешать операции Rent и Return. Затем TCPStream.Dispose() будет Return любых ранее Rent редактируемых объектов и избавится от своих собственных ресурсов, в то время как фактические объекты пула будут удалены только тогда, когда будет ликвидирована служба пула (которую можно установить на TCPServerнеисправность). В настоящее время у вашего TCPStream слишком много обязанностей, что не позволяет вам правильно реализовать одноразовый шаблон.

...