2015-02-05 121 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

发生这种情况,因为定时器引起多线程访问你的上下文类的同一个实例,而当第二个线程试图使用类,它是忙仍在试图创建模型。

您有几个选项可以纠正。我认为最简单的方法是在应用程序或表单加载时禁用第二个计时器,并且仅在第一个计时器代码的第一次迭代运行后才启用它。

或者,您可以让每个计时器使用自己的上下文实例。

或者您可以捕获异常并退出该方法,并等到下一次使用该上下文对象。