2013-10-12 2 views
2

중첩 된 개인 클래스가있는 다음 클래스가 있는데 NID 값을 Context에 할당하고 싶습니다. getter와 setter를 사용했지만 NID (Sequencer.Context = value;)의 값은 (SeqNode = Node.LoadNode(Context);)에 할당되지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?개인 중첩 클래스의 개인 필드 값을 설정하는 방법은 무엇입니까?

//Instantiation 
Increment.NID = "/Root/Dir/NodetoIncrement"; 
String getSequence = Convert.ToString(Increment.SID); 

// The Class 
public static class Increment 
{ 
    //Value of the node Context location in the tree to increment (Increment.NID) 
    public static string NID 
    { 
     set { Sequencer.Context = value; } //The "/Root/Dir/NodetoIncrement"; 
    } 

    //Get the sequence ID 
    public static int SID 
    { 
     get { return Sequencer.GetSeqId; } 
    } 

    //Nested sequencer class. This increments the node. 

    private class Sequencer 
    { 
     private Node SeqNode; 
     private static int SequenceNumber; 
     private volatile bool Run = true; 

     public static string Context { get; set; } //gets 

     public static int GetSeqId 
     { 
      get 
      { 
       return Interlocked.Add(ref SequenceNumber, 1); 
      } 
     } 

     public Sequencer() //Constructor Here! 
     { 
      SeqNode = Node.LoadNode(Context); 
      SequenceNumber = Convert.ToInt16(SeqNode["LastSequenceNo"]); 

      //NEVER DO THIS .. causes the system to lockup see comments. 
      System.Threading.Tasks.Task.Factory.StartNew(() => 
      { 
       while (Run) 
       { 
        Save(); 
        Thread.Sleep(5000); 
       } 
      }); 
     } 

     private void Save() 
     { 
      //optimistic concurrency recommended!! 
      var retryMaxCount = 3;    // maximum number of attempts 
      var cycles = 0;     // current attempt 
      Exception exception = null;  // inner exception storage 
      while (cycles++ < retryMaxCount) // cycle control 
      { 
       try 
       { 
        SeqNode["LastSequenceNo"] = Convert.ToString(SequenceNumber); 
        SeqNode.Save(); 

        // successful save, exit loop 
        exception = null; 
        break; 
       } 
       catch (NodeIsOutOfDateException e) 
       { 
        exception = e; // storing the exception temporarily 
        SeqNode = Node.LoadNode(Context); 
       } 
      } 
      // rethrow if needed 
      if (exception != null) 
       throw new ApplicationException("Node is out of date after 3 attempts.", exception); 
     } 


     ~Sequencer() { Save(); } 

    } 
} 

public class XYHandler : Node 
{ 
    public override void Save(NodeSaveSettings settings) 
    { 
     base.Name = Convert.ToString(Increment.SID); 
     base.Save(); 
    } 

    public override bool IsContentType 
    { 
     get { return true; } 
    } 
} 
+0

, 클래스는 이미 비공개입니다. 그냥 공개하고 문제를 해결하십시오. –

+0

당신이 우리를 도와 줄 수있는 충분한 정보를 제공했다고 생각하지 않습니다. –

+0

인스턴스를 추가했습니다. – Xdrone

답변

0

여기에 약간의 시간 결합이 있습니까?

SeqNodeSequencer이 인스턴스화 될 때 설정되지만 샘플에서 인스턴스화를 볼 수 없습니다.

정적 생성자는 처음에 속성 setter를 호출하기 전에 실행 한 다음 5 초 후에 다시 시도하십시오 - 속성이 설정되는 시점은 언제입니까?

+0

예 시간 커플 링이 여기에 있습니다! 시퀀서가 증가하기 전에 증가 할 노드가 SeqNode로 전달됩니다. "정적 생성자가 속성 setter가 처음 호출되기 전에 실행 된 다음 5 초 후 다시 시도 - 속성이 설정되는 시점은 언제입니까?" 생성자 (SeqNode = Node.LoadNode (Context);)는 NID의 값을 반환해야하는 컨텍스트 게터를 발생시켜야합니다. – Xdrone

0

어디에서 시퀀서가 생성되고 있는지 알 수 없습니다 (아마도 놓친 것 같습니다). 그것은 정적 생성자가 아니기 때문에 LoadNode를 실행하기 위해 적어도 한 번 호출되어야합니다. 그 생성자를 정적으로 만들려고 했습니까?

+0

생성자에 주석을 추가했습니다. – Xdrone

+0

주석을 추가한다고해서 생성자가 정적이되는 것은 아닙니다. 이것 좀보세요 : http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx – Dweeberly

+0

"나는 어디에서 시퀀서가 만들어지고 있는지를 볼 수 없다 (아마도 나는 그것을 놓쳤다)."라고 대답했다. – Xdrone

7

내가 뭘 잘못하고 있니?

정적 초기화 프로그램에서 다른 스레드를 기다리고 있습니다. 절대하지 마십시오. 얼마나 위험한지를 충분히 강조 할 수는 없습니다. 이 답을하는 이유에 대한 설명은

는 : 필드가 개인 제작에 어느 시점이 아닌

https://stackoverflow.com/a/8883117/88656

+0

고개를 가져 주셔서 감사합니다. 그러나 제 질문은 지금입니다. 이 시나리오에서 스레딩을 구현하고 잠금을 피하는 최선의 방법은 무엇입니까? – Xdrone

+0

@xdrone : 그냥 가지 마세요. 정적 생성자는 일부 정적 필드를 초기화해야합니다. 멋지게하지 마라. –

관련 문제