我在wep api中配置了ninject,如下所示。我创建了两个内核对象,一个在请求范围内,另一个在线程范围内:
var requestKernel = new StandardKernel();
requestKernel.Bind<IGlobalDbContext>().ToConstructor(ctx => new GlobalDbContext(Configuration.GlobalDbContext)).InRequestScope();
var threadKernel = new StandardKernel();
RegisterServices(threadKernel);
threadKernel.Bind<IGlobalDbContext>().ToConstructor(ctx => new GlobalDbContext(Configuration.GlobalDbContext)).InThreadScope();
new Kernel(threadKernel);
这里的新内核是用于创建线程范围DBContext
的类:
public class Kernel
{
private static StandardKernel _kernel = null;
public Kernel(StandardKernel kernel)
{
if (_kernel == null)
{
_kernel = kernel;
}
}
public static IKernel GetKernel
{
get
{
return _kernel;
}
}
}
现在,我在以下操作方法中创建了两个任务:
[HttpPost]
public void RunThreadrequest()
{
ThreadFactory threadFactory = new ThreadFactory();
DateTime fromDate = Convert.ToDateTime("2018-05-01");
DateTime toDate = Convert.ToDateTime("2018-05-31");
List<int> orders = _orderManager.All().Where(o => o.IsActive && (o.DeliveryDate >= fromDate && o.DeliveryDate <= toDate)).Select(o => (int)o.Id).ToList();
int length = 2;
int i = 0;
int startIndex = 0;
int endIndex = orders[0] - 1;
do
{
startIndex = endIndex + 1;
endIndex = startIndex + 5;
OrderIndex ordIndexObj = new OrderIndex { StartIndex = startIndex, EndIndex = endIndex };
threadFactory.CreateThread((ordIndex) =>
{
ParameterConfigurationController controller = (ParameterConfigurationController)(Kernel.GetKernel.GetService(typeof(ParameterConfigurationController)));
controller.UpdateOrders(((OrderIndex)ordIndex).StartIndex, ((OrderIndex)ordIndex).EndIndex);
}, ordIndexObj);
i++;
} while (i < length);
threadFactory.Run();
}
public struct OrderIndex
{
public int StartIndex { get; set; }
public int EndIndex { get; set; }
public int ThreadId { get; set; }
public int Index { get; set; }
}
上面的代码将创建两个线程并调用方法UpdateOrders
:
public void UpdateOrders(int startIndex, int lastIndex)
{
var orders = _orderManager.All().Where(o => o.Id >= startIndex && o.Id <= lastIndex).ToList();
foreach (Order order in orders)
{
order.StatusId = 11;
}
_orderManager.SaveChanges();
}
线程代码:
class ThreadFactory
{
private List<Task> threads = new List<Task>();
private CancellationTokenSource source = new CancellationTokenSource();
private CancellationToken token;
public ThreadFactory()
{
token = source.Token;
}
public void CreateThread(Action<object> action, OrderIndex ordObj)
{
if (token.IsCancellationRequested)
token.ThrowIfCancellationRequested();
Task task = Task.Factory.StartNew(action, ordObj, token);
threads.Add(task);
}
public void Run()
{
Task.WaitAll(this.threads.ToArray());
}
}
我观察到的是:当在一个线程中调用SaveChanges
并刷新数据库时,状态为11的记录将不受影响。当第二个线程完成其执行后,记录将生效。
我的问题是,
1)InThreadScope()
是每个线程创建一个dbcontext
还是多个dbcontext
?
2)Task.WaitAll
是否维护任何事务,以便所有线程执行都将立即提交
如果我有任何遗漏,请提出建议。