在析构函数中使用HttpClient

时间:2016-04-13 16:33:25

标签: c# destructor dotnet-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使一个线程发送它的请求,但析构函数最终确定,对象在执行之前就会丢失。

那么:什么是在程序关闭时发布这些数据的好方法? 这段代码失败的原因是什么?

2 个答案:

答案 0 :(得分:2)

你在错误的地方做这件事。

您应该覆盖OnFormClosing方法或为OnClosing事件设置处理程序。

这样做的原因是您不需要在用户界面中出现任何随机的怪异 - 您尝试执行的日志记录应该在之间在程序(或用户)之间发生调用“关闭”,但在表单从视图中消失之前。您甚至可以将鼠标指针更改为“Timer”。如果您执行日志记录异步,请考虑是否在发生DoEvents时重复调用DoEvents,以防止UI在HTTP请求需要一段时间后显示已锁定。

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

答案 1 :(得分: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客户端异步任务完成。