繁体   English   中英

.NET中终结器的HttpClient请求

[英]HttpClient request in finalizer in .NET

我想在垃圾收集器收集对象时发出HTTP请求。 我在类的finailzer中放置了一个简单的调用,只要应用程序没有关闭,该调用就可以正常工作。

当程序完成并且我的应用程序想要关闭时,GC像以前一样调用终结器,但是这次请求被卡住或只是退出而没有异常。 至少Studio没有显示异常,该程序只是在发送呼叫时终止。

不幸的是,我必须使用终结器来发送此请求,因此请不要建议使用Dispose代替终结器。 如果可能的话,让我们找到一种从那里做的方法。 :)

这是我的代码的重要部分:

class MyExample
{
    private readonly HttpClient myClient;

    public MyExample()
    {
        var handler = new HttpClientHandler();
        handler.UseProxy = false;
        handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;

        this.myClient = new HttpClient(handler);
        this.myClient.BaseAddress = new Uri("https://wonderfulServerHere");
    }

    public async void SendImportantData() => await this.myClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "ImportantData"));

    ~MyExample()
    {
        this.SendImportantData();
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyExample ex = new MyExample();

        /* ... */

        ex = new MyExample();

        /* ... */

        GC.Collect();
        GC.WaitForPendingFinalizers(); // Works fine here

       /* ... */
    } // Doesn't work here
}

您在这里撞墙。 不能保证在所有情况下都可以执行终结器:

.net终结器是否始终执行?

终结器可能无法运行,例如,在以下情况下:

Another finalizer throws an exception.
Another finalizer takes more than 2 seconds.
All finalizers together take more than 40 seconds.
An AppDomain crashes or is unloaded (though you can circumvent this with a critical finalizer (CriticalFinalizerObject, SafeHandle or something like that)
No garbage collection occurs
The process crashes

这就是为什么除了少数情况下不建议使用终结器的原因:终结器是为以下目的而设计的: https : //csharp.2000things.com/tag/finalizer/

 Implement a finalizer only when the object has unmanaged resources to clean up (eg file handles) Do not implement a finalizer if you don't have unmanaged resources to clean up The finalizer should release all of the object's unmanaged resources Implement the finalizer as part of the dispose pattern, which allows for deterministic destruction The finalizer should only concern itself with cleanup of objects owned within the class where it is defined The finalizer should avoid side-effects and only include cleanup code The finalizer should not add references to any objects, including a reference to the finalizer's own object The finalizer should not call methods in any other objects 

您是否尝试过ex = null; GC.Collect();之前GC.Collect();

令人难以置信的是,提出一个HTTP请求,并且通常在终结器中进行任何不重要的事情。 期望即使在您的应用程序关闭时也能正常工作,这超出了您的构想。 那时,负责传递HTTP请求的堆栈的一部分可能已经被垃圾回收了。 您几乎没有机会使其正常工作。 您唯一希望做的就是在Main()返回之前调用GC.WaitForPendingFinalizers()期间。

但是,您仍在尝试从终结器内部处理过于复杂的内容。 如果您四处寻找“强制处置”模式,那么您会发现以下建议:终结器应该做的唯一事情是产生一个错误日志条目,该错误条目涉及某个程序员在某个地方忘记调用Dispose()的事实。

如果您坚持在完成时进行实际工作,建议您重写析构函数,以将“重要数据”添加到队列中,然后让其他对象处理该队列。 当然,此处理都需要 Main()的最后一个} 之前完成。 一旦您经过Main()的最后一个} ,“就有龙”。

暂无
暂无

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

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