2017-04-10 61 views
1

我想在垃圾收集器收集对象时发出HTTP请求。我在这个班的最后一班给了一个简单的电话,只要应用程序没有关闭,工作正常。在.NET终结器中的HttpClient请求

当程序结束后,我的应用程序要关闭,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 
} 
+0

你怎么知道它不工作?没有例外的退出代码并不能证明它不起作用。你有意做一个POST并包含一些数据而不是GET吗?有没有可能终结者只是没有被调用的对象? – Luke

+0

好问题。请求根本不在另一边显示。真正的代码使用POST,这与GET示例没有任何区别。 –

+1

当运行时正在终止时,您无法做到这一点。但我很好奇什么情况可能导致需要在终结器中发出Web请求? – Evk

回答

0

你以前GC.Collect();

试图ex = null;配售的HTTP请求,一般做任何不平凡的,从内终结,是蛮横无理的。即使您的应用程序正在关闭,也期望能够正常工作,这是超乎想象的。那时,负责发送HTTP请求的堆栈的一部分可能已经被垃圾收集。你得到它的机会很少。你只有这个不断努力的希望是前你Main()回到GC.WaitForPendingFinalizers()在通话过程中。

但是,你仍然试图从你的终结器内做太复杂的东西。如果你对“强制处置”模式进行谷歌搜索,你会发现一个建议,即终结器应该做的唯一事情就是生成一个关于某个程序员忘记调用Dispose()的事实的错误日志条目。

如果你坚持在定稿做实际工作,我会建议你重写析构函数为您的“重要数据”添加到队列中,并让其他对象的过程这个队列。当然,之前Main()最后}这种处理将全部需要。一旦你超过Main()的最后},“有龙”。

+0

至少现在我知道肯定它不会工作:)谢谢 –

2

你在这里碰壁。 终结不能保证所有的条件下执行:

Are .net finalizers always executed?

终结可能无法运行,例如,如果:

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 (e.g. 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 
+0

那么在这种情况下,终结器被执行,但它不会执行到最后 – Evk