问题
I have created a WCF service with the configuration as InstanceMode=PerCall and ConcurrencyMode=Multiple.
But I am getting problem in the synchronization with one of the instance method. It sometimes does not get called with right set of Class property values.
[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 looks like this:-
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);
}
}
}
}
The [Step-5] is giving me lot of trouble. I even added the lock(_locker) block to contain the ORM call but still no luck. Sometimes the data does not get saved into the db due to the concurrency mode =Multiple. The problem occurs randomly and difficult to nail it down.
But when i flip the concurrency Mode=Single, it works like a charm.
I wish to know, what changes should i add to make it work for Multiple concurrency mode. PartnerChunkProcessor is a simple class with the required set of properties, i think its here that the synchronization problem is occurring.
Please advise.
来源:https://stackoverflow.com/questions/42837277/wcf-multiple-concurrency-issue-with-instance-method-call