C# 返回任务<;int>;冻结用户界面?
我有一个通用方法:C# 返回任务<;int>;冻结用户界面?,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,我有一个通用方法: public static async Task<int> SaveChangesWithAuditingAsync<TLogType>(ObjectContext dbContext, DbSet<TLogType> logsSet, CancellationToken cancellationToken, DbChangeTracker changeTracker) where TLogType : class,
public static async Task<int> SaveChangesWithAuditingAsync<TLogType>(ObjectContext dbContext, DbSet<TLogType> logsSet, CancellationToken cancellationToken, DbChangeTracker changeTracker)
where TLogType : class, new()
{
ObjectContext context = ((IObjectContextAdapter)dbContext).ObjectContext;
await context.SaveChangesAsync(SaveOptions.DetectChangesBeforeSave, cancellationToken).ConfigureAwait(false);
var audits = new List<TLogType>();
foreach (var entry in changeTracker.Entries().Where(o => o.State == EntityState.Modified || o.State == EntityState.Added).ToList())
{
var changeType = entry.State.ToString();
Type entityType = GetEntityType(entry);
string tableName = GetTableName(context, entityType);
var audit = new TbCommonHistoryLog
{
ObjectJson = GetEntityAsJson(entry),
TableName = tableName,
};
TLogType t = new TLogType();
t.ChargeFrom(audit);
audits.Add(t);
}
logsSet.AddRange(audits);
int result = 0;
try
{
result = await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
return result;
}
catch (Exception ex)
{
var m = ex.Message;
return result;
}
}
我注意到在SaveChanges
中调用它,没有问题
SaveChanges的async
版本:
public override Task<int> SaveChangesAsync()
{
return SaveChangesWithAuditingAsync(CancellationToken.None);
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
return SaveChangesWithAuditingAsync(cancellationToken);
}
看起来您没有在等待调用SaveChanges()
中的savechangeswitthauditingasync
——这对您没有任何好处。到处添加可能会很痛苦,但如果您不想出现崩溃或挂起,则需要使用该命令。不要使用。Result,它会等待调用线程上的结果可用,阻止进一步执行
当我从重写的SaveChanges()方法调用它时,UI冻结
对。理想情况下,避免这种情况的最佳方法是根本不调用SaveChanges
——只需使用savechangesync
,并从SaveChanges
引发异常,表示不支持同步API
如果这是不可接受的,那么您可以考虑使用。请注意,每种黑客都有自己的缺点,没有一种黑客可以在每种情况下工作您能向我们解释一下.Result
的作用吗?如果你能,那么你知道你的问题。如果你不能,那你为什么要用它呢?不幸的是,这是一个常见的错误。据我所知,这就是我从任务中提取结果的方式,它只是int
Yes,但它是以阻塞方式执行的。所以你做了所有这些异步调用,最后你只需说:嘿,在这里阻塞,直到你能给出结果为止public override int SaveChanges()
最好是public override Task savechangesync()
并等待调用savechangeswitthauditingasync
。当然,这种等待应该一直进行到UIT的调用。当代码在没有泛型的DbContext
类中时,它工作正常。然后,您必须坚持阻塞情况。没有真正的选择。它异步/等待到顶部,否则什么也不做。请阅读,特别是“一路异步”一节,谢谢Stephen,当我调用savechangesync()
时,这个问题发生了:正如我的评论所说,我设法解决了它。通过一个变通办法。
public override Task<int> SaveChangesAsync()
{
return SaveChangesWithAuditingAsync(CancellationToken.None);
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
return SaveChangesWithAuditingAsync(cancellationToken);
}
private async Task<int> SaveChangesWithAuditingAsync(CancellationToken cancellationToken)
{
return await AuditHelper.SaveChangesWithAuditingAsync(((IObjectContextAdapter)this).ObjectContext, TbHistoryLog, cancellationToken, ChangeTracker);
}