我花了好几个小时试图搞清楚(标题)。所以我有两种方法:
public virtual TEntity GetByName(Expression<Func<TEntity, bool>> whereName)
{
return this.DbEntitySet.FirstOrDefault(whereName);;
}
和
public virtual async Task<TEntity> GetByNameAsync(Expression<Func<TEntity, bool>> whereName)
{
try
{
return await this.DbEntitySet.FirstOrDefaultAsync(whereName);
}
catch (AggregateException ae)
{
throw;
}
catch (Exception ex)
{
throw;
}
}
第一种方法按预期工作,但第二种方法如果找到则运行正常但是
进入一个永无止境的过程,如果不是。我希望抛出异常(可能通过AggregateException
),即使它没有抛出TimeOutException。我试着修改它:
public virtual async Task<TEntity> GetByNameAsync(Expression<Func<TEntity, bool>> whereName)
{
try
{
TimeSpan ts = TimeSpan.FromMilliseconds(5000);
Task<TEntity> task = this.DbEntitySet.FirstOrDefaultAsync(whereName);
if (!task.Wait(ts))
{
throw new TimeoutException();
}
return await task;
}
catch (AggregateException ae)
{
throw;
}
catch (Exception ex)
{
throw;
}
}
然后此方法运行正常WITHOUT ANY exception
。
请帮忙吗?
这就是我如何称呼这种方法(从开始)
//1
var activityManager = HttpContext.Current.GetOwinContext().Get<ActivityManager<ActivityModels>>();
activityManager.CreateAsync(model).GetAwaiter().GetResult();
//2
public virtual async Task<WebCoreResult> CreateAsync(TActivity activity)
{
this.ThrowIfDisposed();
if ((object)activity == null || string.IsNullOrEmpty(activity.ActivityName))
throw new ArgumentNullException(nameof(activity));
try
{
WebCoreResult result = await ActivityExistAsync(activity);
if (result.Succeeded)
return result;
}
catch (Exception)
{
throw;
}
//code removed for brevity
}
//3
public async Task<WebCoreResult> ActivityExistAsync(TActivity activity)
{
var a = await FindByNameAsync(activity.ActivityName);
//var a = FindByName(activity.ActivityName); //this one ok
if (a == null)
{
return await Task.FromResult(new WebCoreResult("Activity not exist"));
}
return await Task.FromResult(WebCoreResult.Success);
}
//4
public virtual async Task<TActivity> FindByNameAsync(string activityName)
{
this.ThrowIfDisposed();
if (activityName == null)
throw new ArgumentNullException(nameof(activityName));
return (TActivity)await this._activityStore.FindByNameAsync(activityName);
}
//5
public async Task<ActivityModels> FindByNameAsync(string name)
{
this.ThrowIfDisposed();
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("activityname");
}
return await _activityStore.GetByNameAsync(x => x.ActivityName.ToLower() == name.ToLower());
}
//6 finale: GetByNameAsync method above
答案 0 :(得分:1)
这个问题可能是由这一行导致的:
activityManager.CreateAsync(model).GetAwaiter().GetResult()
对GetResult
的调用强制线程阻塞,直到Awaiter
完成。所以你阻止了ASP.NET的主循环。一旦await
尝试继续执行,问题就会发生。此时,它将安排连接到ASP.NET主线程的SynchronizationContext
中的延续。但是这个延续从未执行过,因为该线程被阻止为GetResult
。
这就是你可能造成僵局的原因。
有一些方法可以解决这个问题。
await
与Wait()
和GetResult()
混在一起。如果你只使用其中之一,你会没事的。SynchronizationContext
的线程,则需要确保使用await
的函数不会尝试恢复此上下文。最简单的方法是将初始调用包装成Task.Run(() => ...)
。那可行。
通过查询SynchronizationContext
,您可以查看当前线程中是否有System.Threading.SynchronizationContext.Current
处于活动状态。如果是null
或System.Threading.SynchronizationContext
的实例你没事。如果是任何特殊实现,您需要注意。await
次来忽略当前SynchronizationContext
。这可以通过在等待的对象上调用ConfigureAwait(false)
来完成。但是,至少在每个涉及的方法中,每个await
都需要这样做。这些方法中的任何一种都可以解决问题。