我正在尝试提高nHibernate(3.3.2.4000)应用程序(.NET 4.0)的性能。当前,我们正在一对一地执行CRUD操作,这会花费很多时间,所以我的计划是使用ConcurrentQueue和Tasks。
我将代码重构为此:
if (text == "Server: -O")
{
Thread NT = new Thread(() =>
{
this.BeginInvoke((Action)delegate ()
{
textBox1.Text = "Guest";
this.Hide();
_clientSocket.Close();
//Usertimer us = new Usertimer(textBox1.Text);
//us.Show();
});
});
NT.Start();
}
else
{
Array.Resize(ref receivedBuf, _clientSocket.ReceiveBufferSize);
//AppendtoTextBox(text);
_clientSocket.BeginReceive(receivedBuf, 0, receivedBuf.Length, SocketFlags.None, new AsyncCallback(ReceiveData), null);
}
catalogRepository的“保存”方法在后台调用此方法:
public void ImportProductsFromXml(string path)
{
List<Product> products = Mapper.GetProducts(path);
var addQueue = new ConcurrentQueue<Product>(productsToAddUpdate);
var updateTasks = new List<Task>();
for (int i = 0; i < 5; i++)
{
var taskId = i + 1;
updateTasks.Add(Task.Factory.StartNew(() => ProcessAddQueue(taskId, products, addQueue)));
}
}
private void ProcessAddQueue(int taskId, List<Product> products, ConcurrentQueue<Product> queue)
{
Product result = null;
while (queue.TryDequeue(out result))
{
try
{
UpdateProducts(products, result);
}
catch (Exception ex)
{
Debug.WriteLine(string.Format("ProcessAddQueue: taskId={0}, SKU={1}, ex={2}", taskId, result.ProductId, ex));
}
}
}
private void UpdateProducts(List<Product> productsFromFile, Product product)
{
...code removed...
CatalogItem parentItem = _catalogRepository.GetByCatalogItemId(category);
...code removed...
_catalogRepository.Save(parentItem);
...code removed...
}
public CatalogItem GetByCatalogItemId(string catalogItemId)
{
using (ISession session = SessionFactory.OpenSession())
{
return session
.CreateCriteria(typeof (CatalogItem))
.Add(Restrictions.Eq("CatalogItemId", catalogItemId))
.List<CatalogItem>().FirstOrDefault();
}
}
所以我的想法是创建一个包含所有产品的并发队列,然后一次处理5个产品。
但是,我收到一个“线程被异常中止”:
public int Add(T entity)
{
using (ISession session = SessionFactory.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
var id = (int) session.Save(entity);
transaction.Commit();
return id;
}
}
我在做什么错了?
答案 0 :(得分:1)
休眠会话旨在用作工作单元。您打开一个会话,在其上打开一个事务,加载您的实体,对其进行修改,调用保存,提交/回滚该事务,然后处置该会话。
您应该使用一个会话来加载您的实体,然后保存它。当前,您正在通过一个会话加载实体,并通过其他会话将其保存。与并发访问结合使用可能会导致问题。
尝试使用相同的休眠会话加载和保存实体。
如上所述使用休眠模式时,它应该是完全线程安全的。请注意,单个休眠会话不是线程安全的。