我对新的 async/await 东西还很陌生。但是,我有以下类(class):
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 进行异步调用。当我从该调用返回并尝试调用 base.LogEvent() 时,我收到一个 ObjectDisposedException,指出“安全句柄已关闭”。
我知道有一些事情正在发生,当等待完成时,必须运行该方法的其余代码。也许它正在其他线程或上下文中运行?如果是这种情况,如何在写入日志时获取当前用户?
感谢您对此的帮助。
编辑 根据 Yuval 的回答,我进行了以下更改,它似乎工作正常。
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,...);
}
}
}
最佳答案
When I return from that call and try to call base.LogEvent(), I get an ObjectDisposedException stating that "Safe Handle has been Closed".
那是因为在调用链的较高位置,有人正在处置您的插件对象,而该对象尚未真正完成异步操作。使用 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
位于调用堆栈更高层的位置。
关于c# - 尝试使用异步方法访问 Thread.CurrentPrincipal 时出现 ObjectDisposedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30577518/