我有这样的工作:
[UnitOfWork]
public override void Execute(CompleteIRHJobArgs args)
{
var robotUserId = _userRepo.GetAll().Where(p => p.UserName == TestaLIMSWPConsts.LIMSRobot).Select(p => p.Id).First();
using (_session.Use(args.TenantId, robotUserId))
{
_instanceReciptHeaderDomainService.SetIRHToCompleteState(args.IRHIds);
}
}
我找到robotUserId
并将其设置为当前用户。但是,当我进入方法SetIRHToCompleteState
之后,_session.UserId.Value
是null
。我认为这是错误的行为。我的ABP版本是4.0.0。
public async Task SetIRHToCompleteState(List<int> irhIds)
{
var irhs = await _instanceHeaderRepo.GetAll().Where(p => irhIds.Contains(p.Id)).ToListAsync();
foreach (var t in irhs)
{
t.FlowState = FlowState.Completed;
t.CompleteDate = Clock.Now;
t.CompleteUserId = _session.UserId.Value;
}
}
有时
var irhs =等待_instanceHeaderRepo.GetAll()...
引发异常:
System.Transactions.TransactionInDoubtException:交易有疑问。 ---> System.Data.SqlClient.SqlException:已存在与此Command关联的打开的DataReader,必须首先将其关闭。 ---> System.ComponentModel.Win32Exception:等待操作超时
答案 0 :(得分:1)
但是进入方法
SetIRHToCompleteState
后,_session.UserId.Value
为空。
SetIRHToCompleteState
是async
,并且在处置using
范围之后继续运行。
由于Execute
不是async
,因此无法await
,但可以呼叫AsyncHelper.RunSync
。
// using Abp.Threading;
using (_session.Use(args.TenantId, robotUserId))
{
AsyncHelper.RunSync(() => _instanceReciptHeaderDomainService.SetIRHToCompleteState(args.IRHIds));
}
这还将避免“打开DataReader”错误。
来自aspnetboilerplate/aspnetboilerplate#1646:
在后台线程中调用,该线程不在异步上下文中。但这不是问题,因为后台作业管理器已经是单线程的,并且不会导致阻塞许多线程。
Hangfire的实现也是如此。