简体   繁体   English

如何安全地处理从 singleton 返回的客户端实例?

[英]How to safely dispose an instance of a client returned from a singleton?

Given I have the following code which is provided as a singleton lifetime service through .net core, how can I safely dispose of a client (it does implement IDisposable) and the create a new one.鉴于我有以下代码通过 .net 核心作为 singleton 终身服务提供,我如何安全地处置客户端(它确实实现了 IDisposable)并创建一个新的。 I'm concerned once I call Dispose the old client, it will be removed and in the meantime any callers that retrieved the client will be pointing at a client that is now disposed.我担心一旦我调用 Dispose 旧客户端,它将被删除,同时检索客户端的任何调用者都将指向现在已处理的客户端。

public class MyClientFactory: IMyClientFactory
{
    private Client { get; set; }

    public async Task<IMyClient> GetClient()
    {
        if (this.Client != null && DoSomeChecksToSeeIfValid())
        {
            return this.Client;
        }
        else
        {
            this.Client?.Dispose();

            this.Client = new MyClient(await DoSomethingToGetNewCredentials());

            return this.Client;
        }
    }
}

If you want to control the lifetime it's best not to return an instance of the object.如果您想控制生命周期,最好不要返回 object 的实例。 But if this doesn't suit you you can use the event model.但如果这不适合您,您可以使用事件 model。

public interface IMyClientManager
{
     void Do(Action<MyClient> action);
}
public interface IMyClient : IDisposable
{
    
}
public sealed class MyClient: IMyClient
{
    public delegate void DisposeHandle();

    public event DisposeHandle DisposeEvent;

    private bool _isDispose;
    public void Dispose()
    {
        if (!_isDispose)
            DisposeEvent?.Invoke();
        _isDispose = true;
    }
}

public class MyClientManager : IMyClientManager
{
    private MyClient Client { get; set; }
    private object _sync = new object();
    private bool DoSomeChecksToSeeIfValid()
    {
        return this.Client != null;
    }

    public void Do(Action<MyClient> action)
    {
        // you can  create connection pull
        while (!DoSomeChecksToSeeIfValid())
        {
            InitClient();
            //todo: connect or setup
        }

        action.Invoke(this.Client);
    }

    private void InitClient()
    {
        if (this.Client == null)
        {
            lock (_sync)
            {
                this.Client ??= new MyClient();
                this.Client.DisposeEvent += Client_DisposeEvent;
            }

        }
    }

    public MyClient Create()
    {
        // you can  create connection pull
        while (!DoSomeChecksToSeeIfValid())
        {
            InitClient();
            
        }

        return this.Client;
    }

    private void Client_DisposeEvent()
    {
        lock (_sync)
        {
            this.Client.DisposeEvent-= Client_DisposeEvent;
            this.Client = null;
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM