0

I have a class as following

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

    }
}

The function UpdateSchedulingRefTable can be called any time from outside world (for instance if someone updates the schedule configuration manually) ProcessScheduledUpdates is called from a windows service every other minute. Problem: Datatable ScheduleConfiguration is updated in the UpdateSchedulingRefTable (called from outside world - say manually) but when i try to use Datatable ScheduleConfiguration in GetAndSaveScheduledUpdate, i get the older version of values....

What am I missing in this stuff???

About EDIT: I thought the stuff i have not shown is quite obvious and possibly not desired, perhaps my structure is wrong :) and sorry for incorrect code previously, i made a simple function call as a thread initialization... sorry for my code indentation too because i don't know how to format whole block...

Edit 2: ProcessScheduledUpdates is called from a windows service (say every second). I am first hitting point [1] (it will automatically hit point [2] and update ScheduleConfiguration), then i manually update DB and hit point [2]. Then i hit point [1] again to just check the status My problem is now, that i get two entirely different copies of ScheduleConfiguration at point [1] and [2].

Edit 3 I think my question is invalid; i wanted to share data betweena a windows form click and a windows service. No matter how many shared things i have, atleast the address space will be different... My bad...

3
  • Could you add the code, where you manipulate the DataTable? Commented Mar 17, 2011 at 7:01
  • You're not posting the code, that communicates with the database, I would presume, that the problem lies there, because IF one method updates data in the database AND another method later reads data from the database - there should be no problems, whether your variables ar static, or not. Commented Mar 17, 2011 at 7:01
  • ProcessScheduledUpdates is called from a windows service and [2] is crossed by a thread ... does it make any difference ??? (could be a really stupid question but things are not working for me :( ) Commented Mar 17, 2011 at 12:16

1 Answer 1

3

Well, for one thing there's no sign that you've got any memory barriers anywhere which would ensure that any writes are fully "flushed" to main memory, and that reads go to main memory instead of using registers etc. Basically you shouldn't use fields shared between threads without some sort of protection.

Now that's a theoretical risk to some extent - it's not clear that that's actually the problem, although it's certainly a real possibility. I strongly suspect there's another problem, but in the code that you haven't shown us. Do you have diagnostics to indicate that the first thread definitely wrote to ScheduleConfiguration?

Sign up to request clarification or add additional context in comments.

4 Comments

well, i just intentionally didn't check any memory barriers. i wanted to check while debugging... assuming that everything is safe...
@Umer: It's not safe, basically. You should either use locking or some other sort of memory barrier, when changing shared variables. But my guess is that actually your UpdateSchedulingRefTable method simply isn't going into the section which ends up setting the variable - it has to satisfy various criteria before getting there.
is it possible that even while debugging, such problem could occue (i assume no because each step is executed on our control) ???
@Umer: Probably not - I strongly suspect it's a different problem, e.g. no tables being found.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.