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);
        }