在析构函数中使用 HttpClient
Using HttpClient in destructor
我想在我的程序结束时 post 向服务器发送一些异常数据(如果存在)。
我有一个在主 window 视图模型析构函数上触发的析构函数..
我运行这个:
~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,调试完全停止,无一例外,并且 returns:
The program '[3364] Program.vshost.exe' has exited with code 0 (0x0).
我猜这是因为异步的方式。 POST 使一个线程发送它的请求,但是析构函数结束并且对象在它可以执行之前就丢失了。
那么:什么是 POST 程序关闭时此数据的好方法?
此代码失败的原因可能是什么?
尝试让它异步。
~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 客户端异步任务完成。
你做错地方了。
您应该覆盖 OnFormClosing 方法或为 OnClosing 事件设置处理程序。
这样做的原因是您不需要在用户界面中出现任何随机的怪异现象——您尝试进行的日志记录应该发生在程序运行时间 之间 (或用户)调用 "close",但在表单从视图中消失之前。您甚至可以将鼠标指针更改为 "Timer"。如果您执行异步日志记录,请考虑是否在它发生时重复调用 DoEvents,以防止 UI 在 HTTP 请求需要一段时间时看起来已被锁定。
OnFormClosing:https://msdn.microsoft.com/en-us/library/system.windows.forms.form.onformclosing(v=vs.110).aspx
关闭时: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
我想在我的程序结束时 post 向服务器发送一些异常数据(如果存在)。
我有一个在主 window 视图模型析构函数上触发的析构函数..
我运行这个:
~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,调试完全停止,无一例外,并且 returns:
The program '[3364] Program.vshost.exe' has exited with code 0 (0x0).
我猜这是因为异步的方式。 POST 使一个线程发送它的请求,但是析构函数结束并且对象在它可以执行之前就丢失了。
那么:什么是 POST 程序关闭时此数据的好方法? 此代码失败的原因可能是什么?
尝试让它异步。
~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 客户端异步任务完成。
你做错地方了。
您应该覆盖 OnFormClosing 方法或为 OnClosing 事件设置处理程序。
这样做的原因是您不需要在用户界面中出现任何随机的怪异现象——您尝试进行的日志记录应该发生在程序运行时间 之间 (或用户)调用 "close",但在表单从视图中消失之前。您甚至可以将鼠标指针更改为 "Timer"。如果您执行异步日志记录,请考虑是否在它发生时重复调用 DoEvents,以防止 UI 在 HTTP 请求需要一段时间时看起来已被锁定。
OnFormClosing:https://msdn.microsoft.com/en-us/library/system.windows.forms.form.onformclosing(v=vs.110).aspx
关闭时: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