WCF实例方法调用的多个并发问题

时间:2017-03-16 14:43:11

标签: c# web-services wcf locking

我创建了一个WCF服务,其配置为InstanceMode = PerCall和ConcurrencyMode = Multiple。

但是我在与其中一个实例方法的同步中遇到了问题。有时不会使用正确的Class属性值调用它。

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class InvestorService : IInvestorService

 public void ProcessPartnerChunk(short PartnerChunkTypeId, int JobID, int? PartnerID, string serializedChunk, string ClientName)
    {
        PartnerChunkProcessor pcp = new PartnerChunkProcessor(JobID, PartnerID, serializedChunk, ClientName);

        switch ((PartnerChunkType)PartnerChunkTypeId)
        {
            case PartnerChunkType.ChunkTypeX:
                pcp.ProcessChunkStageX();
                break;
            case PartnerChunkType.ChunkTypeY:
                pcp.ProcessChunkStageY();
                break;                
            default: break;
        }

PartnerChunkProcessor如下所示: -

  public class PartnerChunkProcessor
{
    private static object _syncLocker = new object();

    #region "Properties"
    public int? PartnerID { get; set; }
    public int K1JobId { get; set; }
    public string SerializedChunk { get; set; }

    public string Client { get; set; }
    #endregion

    #region "Constructors"
    private PartnerChunkProcessor() { }

    public PartnerChunkProcessor(int K1JobID, int? PID, string Chunk, string ClientName)
    {
        K1JobId = K1JobID;
        PartnerID = PID;
        SerializedChunk = Chunk;
        Client = ClientName;
    }

    #endregion

    public void ProcessChunkStageX()  //IDMS_PartnerTradeGroups
    {           

        DataModelEntities dmxContext = new DataModelEntities();                      

        //[Step-1]
        //Deserialize the incoming XML data into the original business obj.
        List<IDMS_PartnerTradeGroups> chunkPTG = SerializerManager.Deserialize<List<IDMS_PartnerTradeGroups>>(SerializedChunk);

        //[Step-2]
        ////Dummy manipulation of the dataset (Business Logic evaluation).
        List<IDMS_PartnerTradeGroups> lstTarget = new List<IDMS_PartnerTradeGroups>();

        foreach (IDMS_PartnerTradeGroups ptx in chunkPTG)
        {
            lstTarget.Add(ptx);                               
        } 

        ////Add a record with the total value of NumberOfUnits for the partner.
        if (lstTarget.Count > 0)
        {
            decimal? totalUnits = lstTarget.Sum(sx => sx.NumberOfUnits);

            lstTarget.Add(new IDMS_PartnerTradeGroups
                                                                        {
                                                                            PartnerID = Convert.ToInt32(PartnerID),
                                                                            CalendarMonth = 12,
                                                                            CalendarYear = DateTime.Now.Year,
                                                                            NumberOfUnits = totalUnits,
                                                                            PartnerGroupID = "0",
                                                                            TransactionMonth = 1,
                                                                            TransactionYear = DateTime.Now.Year
                                                                        });
        }

        //[Step-3]
        ////Serialize the calculated object into the XML and save it in DB.
        if (lstTarget.Count > 0)
        {
            string targetSerializedXML = SerializerManager.Serialize<List<IDMS_PartnerTradeGroups>>(lstTarget);

            dmxContext.uspSave_IDMS_PartnerTradeGroups_Data(PartnerID, targetSerializedXML, false);

            //[Step-4] Save the Serialized output into REDIS server.
            PersistToRedis(targetSerializedXML, "IDMS_PartnerTradeGroups", MethodBase.GetCurrentMethod().Name, PartnerID, Client);

            //[Step-5]
            //Update the Chunk-Call-Stack status
            lock (_syncLocker)
            {
                UpdateChunkCall((int)Constants.PartnerChunkType.ChunkTypeX, K1JobId, PartnerID);
            }
        }
    }

    private void UpdateChunkCall(int partnerChunkTypeId, int k1JobId, int? partnerId)
    {
        ChunkCallStack currChunkStack = new ChunkCallStack();
        DataModelEntities dmContext = new DataModelEntities();

        currChunkStack = dmContext.ChunkCallStacks.Where(wx => wx.K1JobId == k1JobId
                                                                                    && wx.PartnerId == partnerId
                                                                                    && wx.ReadyToRetire == false
                                                                                    && wx.PartnerChunkTypeId == partnerChunkTypeId)
                                                                                    .FirstOrDefault<ChunkCallStack>();
        if (currChunkStack != null)
        {
            currChunkStack.ChunkStatus = 20;  ////Completed
            currChunkStack.Message = "Processing Complete";
            currChunkStack.DateUpdated = DateTime.UtcNow;
            currChunkStack.UpdatedBy = "Investor-Service";
            dmContext.Entry(currChunkStack).State = System.Data.Entity.EntityState.Modified;
            dmContext.SaveChanges();
        }
    }

public void ProcessChunkStageY()  //IDMS_PartnerTradeGroupTimeLine 
    {
        //[Step-1]
        List<IDMS_PartnerTradeGroupTimeLine> chunkPTG = SerializerManager.Deserialize<List<IDMS_PartnerTradeGroupTimeLine>>(SerializedChunk);

        //[Step-2]
        ////Dummy manipulation of the dataset (Business Logic evaluation).            
        List<IDMS_PartnerTradeGroupTimeLine> lstTarget = new List<IDMS_PartnerTradeGroupTimeLine>();

        foreach (IDMS_PartnerTradeGroupTimeLine ptx in chunkPTG)
        {
            lstTarget.Add(ptx);

        }

        ////Add a record with the total value of NumberOfUnits for the partner.

        if (lstTarget.Count > 0)
        {
            decimal totalUnits = lstTarget.Sum(sx => sx.NumberOfUnits);

            lstTarget.Add(new IDMS_PartnerTradeGroupTimeLine
            {
                PartnerID = Convert.ToInt32(PartnerID),
                CalcMonth = 12,
                CalcYear = DateTime.Now.Year,
                NumberOfUnits = totalUnits,
                TradeGroup = "Total",
                TradeMonth = 12,
                TradeYear = DateTime.Now.Year
            });
        }

        //[Step-3]
        ////Serialize the calculated object into the XML and save it in DB.
        if (lstTarget.Count > 0)
        {
            string targetSerializedXML = SerializerManager.Serialize<List<IDMS_PartnerTradeGroupTimeLine>>(lstTarget);

            DataModelEntities dmxContext = new DataModelEntities();
            dmxContext.uspSave_IDMS_PartnerTradeGroupsTimeline_Data(PartnerID, targetSerializedXML, false);


            //[Step-5]
            //Update the Chunk-Call-Stack status
            lock (_syncLocker)
            {
                UpdateChunkCall((int)Constants.PartnerChunkType.ChunkTypeY, K1JobId, PartnerID);

            }
        }
    }

}

[第5步] 给了我很多麻烦。我甚至添加了锁(_locker)块来包含ORM调用,但仍然没有运气。由于并发模式=多次,有时数据不会保存到数据库中。这个问题是随机发生的,很难将其解决。

但是当我翻转并发模式Mode = Single时,它就像一个魅力。

我想知道,我应该添加哪些更改以使其适用于多并发模式。 PartnerChunkProcessor是一个具有所需属性集的简单类,我认为它在这里发生了同步问题。

请告知。

0 个答案:

没有答案