2017-04-10 65 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