0

我的应用程序有两个部分,它们分别进行大量插入和更新,并且由于管理不善,存在死锁。

我正在使用实体框架进行插入和更新。

以下是我的 TestSpool 程序的代码。该程序的目的是在给定的时间间隔内插入 x 条记录。

using System;
using System.Linq;
using System.Threading;
using System.Transactions;
namespace TestSpool
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new TestEntities())
            {
                decimal start = 700001;
                while (true)
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        //Random ir = new Random();
                        //int i = ir.Next(1, 50);
                        var objs = db.BidItems.Where(m => m.BidItem_Close == false);
                        foreach (BidItem bi in objs)
                        {
                            for (int j = 0; j <= 10; j++)
                            {
                                Transaction t = new Transaction();
                                t.Item_Id = bi.BidItemId;
                                t.User_Id = "Ghost";
                                t.Trans_Price = start;
                                t.Trans_TimeStamp = DateTime.Now;
                                start += 10;
                                db.Transactions.AddObject(t);

                            }
                            Console.WriteLine("Test Spooled for item " + bi.BidItemId.ToString() + " of " + 11 + " bids");
                            db.SaveChanges();
                        }

                        scope.Complete();
                        Thread.Sleep(5000);
                    }
                }
            }
        }
    }
}

程序的第二部分是testserverclass,该serverclass应该处理来自testspool的大量事务,并确定事务的最大数量并更新到另一个表。

using System;
using System.Linq;
using System.Transactions;
public class TestServerClass
{

    public void Start()
    {
        try
        {

            using (var db = new TestServer.TestEntities())
            {

                while (true)
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        var objsItems = db.BidItems.Where(m => m.BidItem_Close == false);
                        foreach (TestServer.BidItem bi in objsItems)
                        {
                            var trans = db.Transactions.Where(m => m.Trans_Proceesed == null && m.Item_Id == bi.BidItemId).OrderBy(m => m.Trans_TimeStamp).Take(100);

                            if (trans.Count() > 0)
                            {
                                var tran = trans.OrderByDescending(m => m.Trans_Price).FirstOrDefault();

                                // TestServer.BidItem bi = db.BidItems.FirstOrDefault(m => m.BidItemId == itemid);
                                if (bi != null)
                                {
                                    bi.BidMinBid_LastBid_TimeStamp = tran.Trans_TimeStamp;
                                    bi.BidMinBid_LastBidAmount = tran.Trans_Price;
                                    bi.BidMinBid_LastBidBy = tran.User_Id;

                                }
                                foreach (var t in trans)
                                {
                                    t.Trans_Proceesed = "1";
                                    db.Transactions.ApplyCurrentValues(t);
                                }

                                db.BidItems.ApplyCurrentValues(bi);
                                Console.WriteLine("Processed " + trans.Count() + " bids for Item " + bi.BidItemId);
                                db.SaveChanges();

                            }


                        }
                        scope.Complete();

                    }

                }

            }


        }
        catch (Exception e)
        {
            Start();
        }
    }

}

但是,由于两个应用程序同时运行,它会从第一个测试或服务器应用程序随机快速进入死锁。我如何优化双方的代码以防止死锁?我期待来自测试池应用程序的大量插入。

4

1 回答 1

1

由于它们处理相同的数据并相互获取,我相信最干净的方法是避免同时执行这两个。

可能在数据库上定义一个全局静态变量、互斥体或某种标志。开始执行的人举起旗帜,其他人等待旗帜下降。当标志下降时,另一个升起标志并开始执行。

为避免每个班级的等待时间过长,您可以更改两个班级以每轮仅处理有限数量的记录。您还应该为标志引入最大等待时间。应仔细选择最大记录限制,以确保每个类在比最大等待时间更短的时间内完成其工作。

于 2012-12-26T08:05:06.173 回答