尝试使用异步方法访问Thread.CurrentPrincipal时出现ObjectDisposedException
本文关键字:CurrentPrincipal ObjectDisposedException Thread 访问 异步方法 | 更新日期: 2023-09-27 17:51:20
我对新的async/await内容相当陌生。然而,我有以下类别:
public abstract class PluginBase
{
//Using EF to store log info to database
private EFContext _context = new EFContext();
private int Id = 1;
protected void LogEvent(string event, string details)
{
_context.LogEvents.Add(new LogItem(){
PluginId = this.Id,
Event = event,
Details = details,
User = Thread.CurrentPrincipal.Identity.Name
});
}
}
public class Plugin : PluginBase
{
public void Process()
{
CallWebService();
}
public async void CallWebService()
{
using(var http = new HttpClient())
{
...
var result = await http.PostAsync(memberURI, new StringContent(content, Encoding.UTF8,"application/json"));
if(result.IsSuccessStatusCode)
_status = "Success";
else
_status = "Fail";
LogEvent("Service Call - " + _status,...);
}
}
所以,这个想法是Plugin.Process被调用。它反过来调用CallWebService((。CallWebService对http进行异步调用。PostAsync。当我从那个电话回来并尝试呼叫基地时。LogEvent((,我得到一个ObjectDisposedException,声明"安全句柄已关闭"。
我知道当awaitable完成时,必须运行该方法的其余代码。也许它是在其他线程或上下文中运行的?如果是这种情况,在写入日志时如何获取当前用户?
谢谢你在这方面的帮助。
编辑根据尤瓦尔的回答,我做了以下更改,看起来效果不错。
public void Process()
{
var task = CallWebService();
task.Wait();
}
public async Task CallWebService(List<Member> members)
{
using(var http = new HttpClient())
{
...
using(var result = await http.PostAsync(memberURI, new StringContent content, Encoding.UTF8, "application/json")))
{
if(result.IsSuccessStatusCode)
_status = "Success";
else
_status = "Fail";
LogEvent("Service Call - " + _status,...);
}
}
}
当我从那个电话回来并尝试呼叫基地时。LogEvent((,我得到一个ObjectDisposedException声明"安全句柄已关闭"。
这是因为在调用链的更高层,有人正在处理你的插件对象,而它还没有真正完成异步操作。使用async void
就是在做一个"点火并忘记"的操作。实际上Process
上没有await
,因此任何调用它的人都认为它已经完成并处理了您的对象。
将async void
方法更改为async Task
,await
方法为
public Task ProcessAsync()
{
return CallWebServiceAsync();
}
public async Task CallWebServiceAsync()
{
using (var http = new HttpClient())
{
var result = await http.PostAsync(memberURI,
new StringContent(content,
Encoding.UTF8,
"application/json"));
if (result.IsSuccessStatusCode)
_status = "Success";
else
_status = "Fail";
LogEvent("Service Call - " + _status,...);
}
}
请注意,您还需要将await ProcessAsync
放在调用堆栈的较高位置。