nHibernate和多个任务

时间:2018-08-27 18:20:39

标签: nhibernate concurrency task

我正在尝试提高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;
        }
    }

我在做什么错了?

1 个答案:

答案 0 :(得分:1)

休眠会话旨在用作工作单元。您打开一个会话,在其上打开一个事务,加载您的实体,对其进行修改,调用保存,提交/回滚该事务,然后处置该会话。

您应该使用一个会话来加载您的实体,然后保存它。当前,您正在通过一个会话加载实体,并通过其他会话将其保存。与并发访问结合使用可能会导致问题。

尝试使用相同的休眠会话加载和保存实体。

如上所述使用休眠模式时,它应该是完全线程安全的。请注意,单个休眠会话不是线程安全的。