I have to System.Timers.Timer in my application. The intervals of those timers are 1000 and 120000. And each time they tick, they save some entity to database.
我不得不System.Timers。定时器在我的应用程序。这些计时器的间隔是1000和120000。每次它们滴答,就会把一些实体保存到数据库中。
But sometimes i get this error in my code; The context cannot be used while the model is being created.This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
但有时我在代码中会出现这个错误;在创建模型时不能使用上下文。如果在onmodelcreate方法中使用上下文,或者并发地访问同一上下文实例,则可能引发此异常。注意,DbContext和相关类的实例成员不能保证是线程安全的。
This is my code:
这是我的代码:
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();
}
}
}
1 个解决方案
#1
0
This is happening because the timers are causing multiple threads to access the same instance of your context class, and when the second thread tries to use the class, it is busy still trying to create the model.
这是因为计时器导致多个线程访问上下文类的同一个实例,当第二个线程尝试使用这个类时,它仍然忙于创建模型。
You have a couple of options to rectify. The simplest, I think, would be to disable the second timer when the app or form loads, and enable it only after the first iteration of the first timer's code has run.
你有几个选项可以纠正。我认为,最简单的方法是在应用程序或表单加载时禁用第二个计时器,并且在第一个计时器的第一次迭代运行之后才启用它。
Alternately, you can have each timer use its own instance of the context.
另外,您可以让每个计时器使用它自己的上下文实例。
Or you could catch the exception and exit the method, and wait until the next time around to use the context object.
或者您可以捕获异常并退出方法,并等待下一次使用上下文对象。
#1
0
This is happening because the timers are causing multiple threads to access the same instance of your context class, and when the second thread tries to use the class, it is busy still trying to create the model.
这是因为计时器导致多个线程访问上下文类的同一个实例,当第二个线程尝试使用这个类时,它仍然忙于创建模型。
You have a couple of options to rectify. The simplest, I think, would be to disable the second timer when the app or form loads, and enable it only after the first iteration of the first timer's code has run.
你有几个选项可以纠正。我认为,最简单的方法是在应用程序或表单加载时禁用第二个计时器,并且在第一个计时器的第一次迭代运行之后才启用它。
Alternately, you can have each timer use its own instance of the context.
另外,您可以让每个计时器使用它自己的上下文实例。
Or you could catch the exception and exit the method, and wait until the next time around to use the context object.
或者您可以捕获异常并退出方法,并等待下一次使用上下文对象。