2015-02-05 117 views
-1

我必須在我的應用程序中使用System.Timers.Timer。這些定時器的間隔是1000和120000.每次他們打勾時,他們都會將一些實體保存到數據庫中。EF6 linq to sql創建模型時無法使用上下文

但有時我在我的代碼中得到這個錯誤;創建模型時無法使用上下文。如果在OnModelCreating方法內使用上下文,或者同時由多個線程訪問同一上下文實例,則可能會引發此異常。請注意,DbContext和相關類的實例成員不保證是線程安全的。

這是我的代碼:

  using ACTMULTILib; 
      using System; 
      using System.Collections.Generic; 
      using System.Diagnostics; 
      using System.IO; 
      using System.Linq; 
      using System.Runtime.InteropServices; 
      using System.Text; 
      using System.Threading.Tasks; 

      namespace RenderingPlcScanner 
      { 
       class Program 
       { 
        [DllImport("kernel32.dll")] 
        static extern IntPtr GetConsoleWindow(); 
        [DllImport("user32.dll")] 
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
        const int SW_HIDE = 0; 
        const int SW_SHOW = 5; 
        private System.Timers.Timer timer1 = new System.Timers.Timer(); 
        private System.Timers.Timer timer2 = new System.Timers.Timer(); 
        private GEOTEKRENDERINGEntities grEntities = new GEOTEKRENDERINGEntities(); 
        private ActEasyIF plc = new ActEasyIF(); 
        private bool isUpToDate = true; 
        private StreamWriter writer; 
        public Program() 
        { 
         grEntities.Database.Connection.Open(); 

         timer1.Interval = 1000; 
         timer1.Elapsed += timer1_Elapsed; 
         timer2.Interval = 120000; 
         timer2.Elapsed += timer2_Elapsed; 
....       
         if (plc.Open() == 0) 
         { 
          timer1.Start(); 
          timer2.Start(); 
         } 
.... 
         Console.ReadLine(); 
        } 

        void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
        { 
     ..... 
     ..... 

         tblSicakSu tSicakSu = new tblSicakSu(); 
         tSicakSu.Seviye = Math.Truncate(seviye * 100)/100; 
         tSicakSu.Sicaklik = Math.Truncate(sicaklik * 100)/100; 
         tSicakSu.Tuketim = tuketim[0]; 
         tSicakSu.Zaman = DateTime.Now; 
         grEntities.tblSicakSu.Add(tSicakSu); 
         grEntities.SaveChanges(); 
        } 

        void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
        { 
         timer1.Stop(); 
         try 
         { 
     ...... 


          DateTime amin = now.AddMinutes(1); 
          short[] set = new short[3]; 
          plc.ReadDeviceBlock2("D5010", 3, out set[0]); 
          //Console.WriteLine(amin.ToString() + " - " + set[0] + "/" + set[1]); 
          if (amin.Hour == set[0] && amin.Minute == set[1] && !tuketimAlindi) 
          { 
           tuketimAlindi = true; 
           short[] tuketim = new short[5]; 
           plc.ReadDeviceBlock2("D3013", 5, out tuketim[0]); 
           tblTuketim tTuketim = new tblTuketim(); 
           tTuketim.Zaman = DateTime.Now; 
           tTuketim.YumusakSu = tuketim[0]; 
           tTuketim.DonusSu = tuketim[2]; 
           tTuketim.SicakSu = tuketim[4]; 
           grEntities.tblTuketim.Add(tTuketim); 
           grEntities.SaveChanges(); 
           //Console.WriteLine("Tüketim alındı"); 
          } 
          else if (amin.Minute != set[1]) 
          { 
           tuketimAlindi = false; 
          } 

          short[] data = new short[1]; 
          plc.ReadDeviceBlock2("D4300", 1, out data[0]); 
          if (data[0] == 0) 
          { 
           short[] sayac = new short[1]; 
           plc.ReadDeviceBlock2("D14000", 1, out sayac[0]); 
           //Console.WriteLine(sayac[0]); 
           if (sayac[0] > 0) 
           { 
            short[] datablock = new short[10]; 
            plc.ReadDeviceBlock2("D15000", 10, out datablock[0]); 
            short uretimID = datablock[0]; 
            short kazanNo = datablock[1]; 
            short malzeme_kodu = datablock[2]; 
            short malzeme_miktari = datablock[3]; 
            short yil = datablock[4]; 
            short ay = datablock[5]; 
            short gun = datablock[6]; 
            short saat = datablock[7]; 
            short dakika = datablock[8]; 
            short saniye = datablock[9]; 
            var vUretim = (from uretim in grEntities.tblUretim where uretim.PartiNo == uretimID select uretim).ToList(); 
            if (vUretim.Count == 0) 
            { 
             tblUretim tUretim = new tblUretim(); 
             tUretim.PartiNo = uretimID; 
             tUretim.KazanNo = kazanNo; 
    .... 
     ...... 

             grEntities.tblUretim.Add(tUretim); 
             grEntities.SaveChanges(); 
             short[] value = new short[1]; 
             value[0] = 1; 
             plc.WriteDeviceBlock2("D4300", 1, ref value[0]); 
            } 
            else if (vUretim.Count == 1) 
            { 
             tblUretim tUretim = vUretim[0];      
    ....  
              short[] partiTavukUnuMiktari = new short[1]; 
      ..... 
             grEntities.SaveChanges(); 
             short[] value = new short[1]; 
             value[0] = 1; 
             plc.WriteDeviceBlock2("D4300", 1, ref value[0]); 
            } 
           } 
          } 

         } 
         catch(Exception ex) 
         { 
          writer.WriteLine("----------------------------------Error (" + DateTime.Now.ToString() + ") ---------------------------------------------------"); 
          writer.WriteLine(ex.Message + " : " + ex.StackTrace); 
          writer.WriteLine("-----------------------------------------------------------------------------------------------------------------------------"); 
          writer.Flush(); 
          //Console.WriteLine(ex.Message + " " + ex.StackTrace); 
         } 
         timer1.Start(); 
        } 

        static void Main(string[] args) 
        { 
         new Program(); 
        } 
       } 
      } 
+0

這是一個巨大的代碼負載。請發佈一個小而完整的問題重現。 – 2015-02-05 13:40:40

+0

我編輯了我的問題 – MOD 2015-02-05 13:52:42

回答

0

發生這種情況,因爲定時器引起多線程訪問你的上下文類的同一個實例,而當第二個線程試圖使用類,它是忙仍在試圖創建模型。

您有幾個選項可以糾正。我認爲最簡單的方法是在應用程序或表單加載時禁用第二個計時器,並且僅在第一個計時器代碼的第一次迭代運行後才啓用它。

或者,您可以讓每個計時器使用自己的上下文實例。

或者您可以捕獲異常並退出該方法,並等到下一次使用該上下文對象。