C# 为了表明第一个线程确实写入了ScheduleConfiguration?
,首先,没有迹象表明您在任何地方有任何内存障碍,可以确保任何写入都完全“刷新”到主内存,读操作进入主内存,而不是使用寄存器等。基本上,在没有某种保护的情况下,不应该使用线程之间共享的字段C# 为了表明第一个线程确实写入了ScheduleConfiguration?,c#,multithreading,static-members,C#,Multithreading,Static Members,,首先,没有迹象表明您在任何地方有任何内存障碍,可以确保任何写入都完全“刷新”到主内存,读操作进入主内存,而不是使用寄存器等。基本上,在没有某种保护的情况下,不应该使用线程之间共享的字段 从某种程度上说,这是一个理论上的风险——不清楚这是否是问题所在,尽管这确实是一个真正的可能性。我强烈怀疑还有另一个问题,但在您没有向我们展示的代码中。您是否有诊断来指示第一个线程确实写入了ScheduleConfiguration?您是否可以添加代码,在其中操作DataTable?您没有发布与数据库通信的代码,
从某种程度上说,这是一个理论上的风险——不清楚这是否是问题所在,尽管这确实是一个真正的可能性。我强烈怀疑还有另一个问题,但在您没有向我们展示的代码中。您是否有诊断来指示第一个线程确实写入了
ScheduleConfiguration
?您是否可以添加代码,在其中操作DataTable?您没有发布与数据库通信的代码,我认为问题就在那里,因为如果一个方法更新数据库中的数据,而另一个方法稍后从数据库中读取数据,那么无论变量是否为静态变量,都应该没有问题。ProcessScheduledUpdates
是从windows服务调用的,[2]是由线程交叉的。。。这有什么区别吗???(这可能是一个非常愚蠢的问题,但事情对我不起作用:()你能在操作DataTable的地方添加代码吗?我想,你没有发布与数据库通信的代码,问题就在那里,因为如果一个方法更新数据库中的数据,而另一个方法稍后从数据库中读取数据,那么应该没有问题,不管你的变量是静态的还是非静态的ProcessScheduledUpdates
是从windows服务调用的,[2]被线程交叉…这有什么区别吗??(这可能是一个非常愚蠢的问题,但事情对我不起作用:()嗯,我只是故意没有检查任何内存障碍。我想在调试时进行检查…假设一切都是安全的…@Umer:基本上,这不安全。在更改共享变量时,你应该使用锁定或其他类型的内存障碍。但我猜这实际上是你的UpdateSchedulingRefTable
方法ply没有进入最后设置变量的部分-它必须满足各种条件才能到达那里。是否有可能即使在调试时,也会出现这样的问题(我假设没有,因为每个步骤都在我们的控件上执行)???@Umer:可能不是-我强烈怀疑这是另一个问题,例如,找不到任何表。我只是故意没有检查任何内存障碍。我想在调试时检查…假设一切都是安全的…@Umer:基本上不安全。在更改sha时,应该使用锁定或其他类型的内存障碍红色变量。但我猜实际上你的UpdateSchedulingRefTable
方法根本没有进入到设置变量的部分——它必须满足各种条件才能到达那里。是否有可能即使在调试时,也会出现这样的问题(我假设没有,因为每个步骤都是在我们的控件上执行的)??@Umer:可能不是-我强烈怀疑这是另一个问题,例如,没有找到表。
public class ScheduledUpdater
{
private static readonly object lockingObject = new object();
private static Queue<int> PendingIDs = new Queue<int>();
private static bool UpdateThreadRunning = false;
private static bool IsGetAndSaveScheduledUpdateRunning = false;
private static DataTable ScheduleConfiguration;
private static Thread updateRefTableThread;
private static Thread threadToGetAndSaveScheduledUpdate;
public static void ProcessScheduledUpdates(int ID)
{
//do some stuff
// if ( updateRefTableThread not already running)
// execute updateRefTableThread = new Thread(new ThreadStart(UpdateSchedulingRefTableInThrear));
// execute updateRefTableThread.Start();
//do some stuff
***[1]***
GetAndSaveScheduledUpdate(ID)
}
private static void UpdateSchedulingRefTableInThrear()
{
//if(updateRefTableThread==true)
// return;
// updateRefTableThread = true
do{
UpdateSchedulingRefTable();
Thread.sleep(800000);
}while(updateRefTableThread);
//updateRefTableThread = false;
}
public static void UpdateSchedulingRefTable()
{
// read DB and update ScheduleConfiguration
string query = " SELECT ID,TimeToSendEmail FROM TBLa WHERE MODE = 'WebServiceOrder' AND BDELETE = false ";
clsCommandBuilder commandBuilder = new clsCommandBuilder();
DataSet ds = commandBuilder.GetDataSet(query);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
List<string> lstIDs = new List<string>();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
lstIDs.Add(ds.Tables[0].Rows[i]["ID"].ToString());
if (LastEmailSend.Contains(ds.Tables[0].Rows[i]["ID"].ToString()))
LastEmailSend[ds.Tables[0].Rows[i]["ID"].ToString()] = ds.Tables[0].Rows[i]["TimeToSendEmail"].ToString();
else
LastEmailSend.Add(ds.Tables[0].Rows[i]["ID"].ToString(), ds.Tables[0].Rows[i]["TimeToSendEmail"].ToString());
}
if (lstIDs.Count > 0)
{
string Ids = string.Join(",", lstIDs.ToArray()).Trim(',');
dhDBNames dbNames = new dhDBNames();
dbNames.Default_DB_Name = dbNames.ControlDB;
dhGeneralPurpose dhGeneral = new dhGeneralPurpose();
dhGeneral.StringDH = Ids;
DataSet result = commandBuilder.GetDataSet(dbNames, (object)dhGeneral, "xmlGetConfigurations");
if (result != null && result.Tables.Count > 0)
{
***[2]***
Monitor.Enter(lockingObject);
if (ScheduleConfiguration != null)
ScheduleConfiguration.Clear();
ScheduleConfiguration = result.Tables[0];
Monitor.Exit(lockingObject);
}
}
}
}
public static void GetAndSaveScheduledUpdate(int ID)
{
***[3]***
//use ScheduleConfiguration
Monitor.Enter(lockingObject);
if (ScheduleConfiguration == null)
{
UpdateSchedulingRefTable();
Monitor.Exit(lockingObject);
}
else
Monitor.Exit(lockingObject);
Monitor.Enter(lockingObject);
DataRow[] result = ScheduleConfiguration.Select("ID = "+ID);
Monitor.Exit(lockingObject);
//then for each result row, i add this to a static Queue PendingIDs
}
}