2016-04-13 8 views
0

私のプログラムが終了したら、いくつかの例外データ(存在する場合)をサーバに投稿したいと思います。デストラクタでHttpClientを使用する

私は、メインウィンドウのビューモデルのデストラクタでトリガされるデストラクタ..

を持って、私はこれを実行します。

~ProgramWizardViewModel() 
{ 
    if ((Program.Errors.Count > 0) 
        && (WizardData?.User != null)) 
    { 
     string errorsText = string.Format(string.Join("\n", Program.Errors)); 
     WizardData.client.UploadExceptionReport(errorsText); 
    } 
} 

WizardData.clientは、メソッドUploadExceptionReportを持っているが(私はSOからコピーされていること)

public void UploadExceptionReport(String s) 
{ 
    using (var client = new HttpClient()) 
    { 
     var uri = new Uri(Program.ServerUri + "api/exception_report"); 
     var content = new FormUrlEncodedContent(new[] 
     { 
      new KeyValuePair<string, string>("exception_string", s) 
     }); 
     var result = client.PostAsync(uri, content).Result; 
     string resultContent = result.Content.ReadAsStringAsync().Result; 
     Console.WriteLine(resultContent); 
    } 
} 

しかしclient.PostAsyncで、デバッグは例外なく、完全に停止し、リターン:

プログラム '[3364] Program.vshost.exe'がコード0(0x0)で終了しました。

私はこれが非同期のためにあると推測しています。 POSTは要求を送信するスレッドを作成しますが、デストラクタは終了し、オブジェクトは実行前に失われます。

So:プログラム終了時にこのデータをPOSTするにはどうすればよいでしょうか? このコードが失敗する理由は何ですか?

+1

多分それは 'AppDomain.UnhandledException'を使用することをお勧めしますか?または、フォーム終了時の他のイベント。 – abatishchev

+1

非同期送信を取り出し、ブロッキング送信を使用してください。非同期では、呼び出し元のスレッドが処理してメインアプリを閉じることができます。 –

答えて

2

あなたは間違った場所でこれをやっています。

OnFormClosingメソッドをオーバーライドするか、OnClosingイベントのハンドラを設定する必要があります。

これは、ユーザーインターフェイスにランダムな奇妙なことは必要ありません。実行しようとしているログは、の間に発生する必要があります。プログラム(またはユーザー)が "close "、しかしフォームが見えなくなる前に。マウスポインタを「タイマー」に変更することもできます。ログ非同期を行う場合は、発生中にDoEventsを繰り返し呼び出すかどうかを検討して、HTTP要求がしばらく時間がかかるとUIがロックされていないようにしてください。

OnFormClosing:https://msdn.microsoft.com/en-us/library/system.windows.forms.form.onformclosing(v=vs.110).aspx

OnClosing:https://msdn.microsoft.com/en-us/library/system.windows.forms.form.closing(v=vs.110).aspx

DoEvents関数:https://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents(v=vs.110).aspx

+0

情報ありがとうございます。そこにコードを置くことは、私には良いデザインセンスです。 MVVMパターンにフォーム・クロージング・イベント・ハンドラを組み込むことが、それほど簡単ではないことが判明しました。 – pgee70

0

非同期にしてください。

~ProgramWizardViewModel() 
{ 
    if ((Program.Errors.Count > 0) 
        && (WizardData?.User != null)) 
    { 
     string errorsText = string.Format(string.Join("\n", Program.Errors)); 
     WizardData.client.UploadExceptionReport(errorsText).Wait(); 
    } 
} 

そして

public async Task UploadExceptionReport(String s) 
{ 
    using (var client = new HttpClient()) 
    { 
     var uri = new Uri(Program.ServerUri + "api/exception_report"); 
     var content = new FormUrlEncodedContent(new[] 
     { 
      new KeyValuePair<string, string>("exception_string", s) 
     }); 
     var result = await client.PostAsync(uri, content); 
     string resultContent = await result.Content.ReadAsStringAsync(); 
     Console.WriteLine(resultContent); 
    } 
} 

たぶん今デストラクタが終了するHTTPクライアントの非同期タスクを待ちます。

関連する問題