2015-04-22 8 views
5

को तोड़ने के लिए एक स्थान स्ट्रिंग को बदलना मैं हाल ही में एक साधारण लोगोफाइल क्लास के साथ पॉप अप करने वाली किसी समस्या के साथ संघर्ष कर रहा हूं।मेरे लॉगर वर्ग

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Threading; 

namespace Assets.Code 
{ 
    class TimingLogger 
    { 
     public static readonly TimingLogger Logger = new TimingLogger(); 
     private static readonly string path = "C:\\Logs\\TimingLog.txt"; 
     private readonly Mutex mutex = new Mutex(false, path); 
     private StreamWriter writer; 
     private readonly Queue<string> queue = new Queue<string>(); 
     private bool isRunning; 
     private readonly object obj = new object(); 

     private TimingLogger() 
     { 

     } 

     public void CheckPath() 
     { 
      if (!File.Exists(path)) 
      { 
       File.Create(path); 
      } 
     } 

     public void Run() 
     { 
      isRunning = true; 
      while (isRunning) 
      { 
       lock (obj) 
       { 
        while (queue.Count <= 0) 
        { 
         Monitor.Wait(obj); 
        } 
        Log(queue.Dequeue()); 
       } 
      } 
     } 

     public void Log(string line) 
     { 
      try 
      { 
       mutex.WaitOne(); 
       writer = File.AppendText(path); 
       writer.WriteLine(line); 
       writer.Close(); 
      } 
      catch (Exception) 
      { 
       //throw; 
      } 
      finally 
      { 
       mutex.ReleaseMutex(); 
      } 
     } 

     public void Enqueue(string line) 
     { 
      lock (obj) 
      { 
       queue.Enqueue(line); 
       Monitor.Pulse(obj); 
      } 
     } 

     public void Stop() 
     { 
      isRunning = false; 
     } 
    } 
} 

यह कक्षा हाल ही में ठीक काम कर रही थी, जब मैंने देखा कि मेरी लॉग फ़ाइल मुझे अपेक्षित डेटा नहीं दिखा रही थी। आश्चर्यजनक रूप से पर्याप्त, मैंने कक्षा की किसी भी कार्यक्षमता को नहीं बदला था। मेरे नए के साथ एक पुराने, कामकाजी संस्करण की तुलना में, केवल अंतर यह था कि मेरे कुछ फ़ील्ड private और readonly बनाए गए थे। इसके अलावा, string path को const में बदल दिया गया था। और मेरे पूर्ण विवेक के लिए, इसे readonly पर बदलकर मेरे द्वारा जारी किए गए मुद्दे को ठीक किया गया।

तो मेरा सवाल है: पृथ्वी पर यह कैसे संभव है? जहां तक ​​मुझे पता है, इस स्थिति में केवल पढ़ने और दृढ़ता के बीच कोई अंतर नहीं होना चाहिए।

डीबगिंग करते समय, व्यवहार में परिवर्तन पर्याप्त है, खासकर Run() विधि में। होना चाहिए कि यहां एक बार Log(queue.Dequeue()); कहा गया है, थ्रेड lock कथन छोड़ देगा और फिर से while (isRunning) लूप के माध्यम से फिर से चला जाएगा। यह बहुत स्पष्ट लगता है, है ना? हालांकि, जब मैं string path को const में बदलता हूं और फिर से डीबग करता हूं, तो Log(queue.Dequeue()); एक बार पास हो जाता है और लॉग फ़ाइल में एक ही कथन पाया जा सकता है, जिसके बाद यह कभी भी कुछ और नहीं करता है। यह while (isRunning) से पहले नहीं आया है और ऐसा लगता है कि यह lock (obj) ब्लॉक नहीं छोड़ता है। Log(queue.Dequeue()); सफलतापूर्वक कॉल करने के बाद लॉगर थ्रेड बस बंद या रोकना प्रतीत होता है।

वास्तव में Log विधि में अपवाद फेंकने से कोई फर्क नहीं पड़ता, कोई अपवाद नहीं फेंक दिया जाता है क्योंकि लॉगिंग स्वयं ठीक काम करती है।

मुझे यह उल्लेख करना चाहिए कि मैं इस कोड का उपयोग यूनिटी 3 डी 5 के साथ कर रहा हूं, जो मोनो का उपयोग करता है। लेकिन फिर भी, इस तरह के एक छोटे से संपादन द्वारा व्यवहार में यह कठोर परिवर्तन मेरे लिए असंभव लगता है। क्या कोई यह समझा सकता है कि यह क्यों हो रहा है?

धन्यवाद!

+0

मैंने सोचा कि यह संदेश के मुख्य भाग लेकिन ठीक अंदर पोस्ट करने के लिए थोड़ा बहुत ज्यादा कोड था, मैंने इसे जोड़ा है। – David

+0

यह एक लिंक से बहुत बेहतर है जो गायब हो सकता है और बाद में आपके प्रश्न को समझ में नहीं आता है। एक लॉगर लिखना एक मुश्किल व्यवसाय है जिसे पहले ही हल कर लिया गया है। मौजूदा समाधान का उपयोग करना बेहतर नहीं होगा जैसे कि [nLog] (http://nlog-project.org/)? – spender

+0

मजेदार है कि आपको इसका जिक्र करना चाहिए, मैंने एनएलओजी की कोशिश की लेकिन मुझे यूनिटी 3 डी 5 के साथ काम करने में कुछ समस्याएं आईं। बस दोहराने के लिए, मेरा लॉगर ठीक काम करता है कि मैंने समस्या को ठीक और ठीक कर दिया है। मैं बस समस्या को समझ नहीं पा रहा हूं। – David

उत्तर

1

यहाँ अंतर है:

Consts फ़ाइलों का मेटाडाटा में बनाए गए हैं, इसलिए जब आप आप कक्षा चलाने के मूल्य पहले से ही वहाँ है।

ReadOnly, संकलन समय में प्रारंभ कर रहे हैं अपने मामले, यहाँ चाल में, भले ही आप तो पहले पथ घोषित म्युटेक्स, संकलक म्युटेक्स वस्तु पहले प्रारंभ, यहाँ क्यों है:

आपका पहला स्थिर करने के लिए वस्तु

public static readonly TimingLogger Logger = new TimingLogger(); 

क्योंकि आप निर्माता कहा जाता है, गैर स्थिर सदस्य प्रारंभ कर रहे हैं, म्युटेक्स अगले सदस्य प्रारंभ करने के लिए कर रही है: प्रारंभ लॉगर है। इस बिंदु पर आपने अभी तक पथ शुरू नहीं किया है, इसलिए आप अपने म्यूटेक्स ऑब्जेक्ट को पैरामीटर झूठी और शून्य के साथ बना रहे हैं।

आप एक ही त्रुटि आप स्थिरांक केवल पढ़ने के लिए उपयोग करने के साथ है करना चाहते हैं, तो आप की तरह एक स्थिर निर्माता का उपयोग कर अपने स्थिर पैरामीटर आरंभीकरण के आदेश के लिए मजबूर कर सकते हैं:

static TimingLogger() 
{ 
    path = "C:\\Logs\\TimingLog.txt"; 
    Logger = new TimingLogger(); 
} 

या बस लॉगर से पहले पथ डाल।

आप स्थिरांक का उपयोग कर त्रुटि है नहीं करना चाहते हैं, तो बस अशक्त पैरामीटर का उपयोग कर म्युटेक्स प्रारंभ बदलने के लिए:

private readonly Mutex mutex = new Mutex(false, null); 
संबंधित मुद्दे