开发者

C#, Can I check on a lock without trying to acquire it?

I have a lock in my c# web app that prevents users from running the update script once it has started.

I was thinking I would put a notification in my master page to let the user know that the data isn't all there yet.

Currently I do my locking like so.

protected void butRefreshData_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ParameterizedThreadStart(UpdateDatabase));
    t.Start(this);
    //sleep for a bit to ensure that javascript has a chance to get rendered
    Thread.Sleep(100);
}


public static void UpdateDatabase(object con)
{
    if (Monitor.TryEnter(myLock))
    {
        Updater.RepopulateDatabase();
        Monitor.Exit(myLock);
    }
    else
    {
        Common.RegisterStartupScript(con, AlreadyLockedJavaScript);
    }
}

And I do not want to do

if(Monitor.TryEnter(myLock))
    Monitor.Exit(myLock);
else
    //show processing labal

As I imagine there is a slight possibility that it might display the notification when it isn't actually running.

Is there an alternative I can use?

Edit:

Hi Everyone, thanks a lot for your suggestions! Unfortunately I couldn't quite get them to work... However I combined the ideas on 2 answers and came up with my own solution. It seems to be working so far but I have to wait for the process to complete...

Ok this seems to be working, I broke out the Repopule Method into it's own class.

public static class DataPopulation
{
    public static bool IsUpdating = false;
    private static string myLock = "My Lock";
    private static string LockMessage = @"Sorry, the data repopulation process is already running and cannot be stopped. Please try again later. If the graphs are not slowly filling with data please contact your IT support specialist.";
    private static string LockJavaScript = @"alert('" 开发者_JS百科+ LockMessage + @"');";
    public static void Repopulate(object con)
    {
        if (Monitor.TryEnter(myLock))
        {
            IsUpdating = true;
            MyProjectRepopulate.MyProjectRepopulate.RepopulateDatabase();
            IsUpdating = false;
            Monitor.Exit(myLock);
        }
        else
        {
            Common.RegisterStartupScript(con, LockJavaScript);
        }
    }
}

In master I do

protected void Page_Load(object sender, EventArgs e)
{
    if (DataPopulation.IsUpdating)
        lblRefresh.Visible = true;
    else
        lblRefresh.Visible = false;
}


(Given that you are aware of the race condition for displaying this notification just after processing stopped.... )

You could switch to a CountdownEvent. This works similarly to a ManualResetEvent, but also provides CurrentCount and IsSet properies, which could be used to determine if something is being processed.


How about just setting a volaltile bool property somewhere that indicates an active lock, perhaps via callback method?


Explore Autoresetevents and ManualResetevents. You can have the spawned thread set the event and check the event in the main thread to display the message.


butRefreshData_Click()
{
    lock(myLock)
    {
        if (isbusy) {/*tell user*/}
    }
}

UpdateDatabase(object con)
{
    lock(myLock)
    {
        if (isbusy) {/*tell user*/ return;}
        else {isbusy = true;}
    }

    Updater.RepopulateDatabase();

    lock(myLock)
    {
        isBusy = false;
    }
}

Note: You should probably wrap UpdateDatabase in a try-finally to avoid isBusy from being stuck true if an exception is thrown.


As I imagine there is a slight possibility that it might display the notification when it isn't actually running.

There will always be the possibility you send the "Working..." message and then immediately the job is finished. What you have should logically work.

public static void UpdateDatabase(object con) 
{ 
    if (Monitor.TryEnter(myLock)) 
    {
       System.Diagnostics.Debug.WriteLine("Doing the work");
        Thread.Sleep(5000); 
        Monitor.Exit(myLock);
        System.Diagnostics.Debug.WriteLine("Done doing the work");
    } 
    else 
    {
        System.Diagnostics.Debug.WriteLine("Entrance was blocked");
    } 
} 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜