C# 如何关闭未实现IDisposable的单例服务

C# 如何关闭未实现IDisposable的单例服务,c#,asynchronous,dependency-injection,idisposable,C#,Asynchronous,Dependency Injection,Idisposable,我有一个单件服务,它与服务总线对话。我的问题是我无法优雅地实现IDisposable,因为对服务总线客户端的“关闭”调用是async-CloseAsync() 因此,我的服务类还实现了一个CloseAsync方法,该方法遵从服务总线客户端的CloseAsync。 据我所知,我的选择包括: 在客户端上调用CloseAsync时实现dispose和block。感觉不对 在startup.cs中初始化成员变量,将其添加为Singleton,使用ApplicationLifetime注册ShutDown

我有一个单件服务,它与服务总线对话。我的问题是我无法优雅地实现
IDisposable
,因为对服务总线客户端的“关闭”调用是
async
-
CloseAsync()

因此,我的服务类还实现了一个
CloseAsync
方法,该方法遵从服务总线客户端的
CloseAsync
。 据我所知,我的选择包括:

  • 在客户端上调用
    CloseAsync
    时实现dispose和block。感觉不对
  • startup.cs
    中初始化成员变量,将其添加为
    Singleton
    ,使用
    ApplicationLifetime
    注册
    ShutDown
    处理程序,并在其中关闭我的客户端。看起来太过分了。(我已经尝试过了,但是我的
    ShutDown
    处理程序中的代码要么没有命中,要么没有运行)
  • 只需离开它,因为应用程序无论如何都将关闭。诱人,但也感觉不对(我喜欢清理)
  • 有没有办法拦截DI容器中服务的处置(我使用的是标准的
    Microsoft.Extensions.DependencyInjection.ServiceCollection

    在Dispose方法中阻止异步调用可以吗?这样我可以让我的班级自我处置


    有没有其他方法可以做到这一点,而我却没有呢?

    如果在应用程序的整个生命周期中只有一个该对象的实例,那么为什么要处理它呢?当应用程序关闭时,操作系统会回收其内存空间,从而有效地处理整个应用程序集及其可能创建的任何资源

    IDisposable
    (显式处理)对于消耗大量内存且在应用程序生命周期内可能多次创建(通常是快速连续创建)的对象类型有意义;例如,
    bitmap
    对象为图像数据、流s和其他承载/操作您多次实例化的对象分配一个大缓冲区。使用块放入
    中的内容

    这里有一条经验法则:

    只有在以下情况下才需要使用
    IDisposable
    :对象的每个实例都会占用大量内存(想想几十兆字节),需要一次创建并保留多个实例,或者需要快速连续创建多个实例。在这些情况下,您将受益于手动处理对象。如果这些不适合您的用例,那么垃圾收集器将完成一项足够的工作来清理未使用的资源


    感谢@Broots提供的有用链接

    如果在应用程序的整个生命周期中只有一个该对象的实例,那么为什么要处理它呢?当应用程序关闭时,其内存空间会被操作系统回收,从而有效地处理整个应用程序集及其可能创建的任何资源。IDisposable对于消耗大量内存并可能多次创建(通常是快速连续创建)的对象类型是有意义的在您的申请有效期内;例如,为图像数据分配大缓冲区的位图对象等与@ArashMotamedi的观点有关:谢谢!这是有道理的,而且肯定是我一直在寻找的答案,因为它使代码保持最干净。也感谢您提供的额外信息,它帮助我知道何时需要担心处理。我想在这种情况下,我会担心的一个问题是消息是否将要发送到服务总线,并且应用程序在发送消息之前关闭。能够等待CloseAsync可能会允许发送这些消息。@brenwebber您当然可以侦听事件(应用程序关闭等)并调用CloseAsync。但这与处理对象不同。如果您选择此路径,请确保在代码中设置了足够的同步和保护,以便在收到应用程序关闭事件后,应用程序的其他部分不会尝试向队列提交新消息。你需要稍微协调一下应用程序的不同部分。@brenwebber如果可能的话,尽量避免这样做。您会发现自己被线程和异步操作纠缠在一起。本质上,问问你自己:丢失一条信息的代价是什么?您将不可避免地以某种方式丢失消息(应用程序崩溃、系统崩溃)。所以,考虑一下你对信息丢失的容忍度,并进行相应的设计。让它尽可能简单,并且只在绝对必要的情况下复杂。