2017-04-10 10 views
1

ガベージコレクタによってオブジェクトが収集されているときにHTTPリクエストを行いたいと思います。クラスのfinailzerに簡単な呼び出しを行います。これは、アプリケーションがシャットダウンしていない限り正常に動作します。.NETのファイナライザでのHttpClientリクエスト

プログラムが終了し、アプリケーションがシャットダウンしたいとき、GCは前と同じようにファイナライザを呼び出しますが、今回は要求がスタックしたり、例外なく終了します。少なくともスタジオは例外を表示しません。コールが送信されると、プログラムは終了します。

残念ながら、このリクエストを送信するにはファイナライザを使用する必要があります。ファイナライザの代わりにDisposeを使用することはお勧めしません。可能であれば、そこからそれを行う方法を見つけましょう。 :)ここで

は、私のコードの重要な部分である:HTTPリクエストを配置し、一般的には非自明な何かをやって

GC.Collect();

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

あなたがファイナライザーの中から、ex = null;を試してみましたは、ひどく不愉快です。あなたのアプリケーションがシャットダウンしているときでさえも動作することを期待することは、あまり考えられません。その時点で、HTTP要求の配信を担当するスタックの一部がすでにガベージコレクションされている可能性があります。あなたはそれを稼働させる機会はほとんどありません。これまでの仕事の唯一の希望はGC.WaitForPendingFinalizers()の前にの前にあなたのMain()が返されます。

しかし、依然としてファイナライザ内から複雑すぎるものをやろうとしています。 "強制的な処分"のパターンについてGoogleを検索した場合、ファイナライザが行うべき唯一のことは、あるプログラマがどこかでDispose()を呼び出すことを忘れたというエラーログエントリを生成することです。

ファイナライズ時に実際の作業を行うことを強くお勧めする場合は、デストラクタを書き換えて「重要なデータ」をキューに追加し、他のオブジェクトにこのキューを処理させることをお勧めします。もちろん、この処理はすべての前に行わなければならず、の最後ののMain()の前に行われます。最後に}Main()を過ぎると、 "そこにはドラゴンズがいる"。

+0

少なくとも今私はそれが動作しないことを知っています:) thanks –

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

関連する問題