views:

1085

answers:

3

I have a form being displayed by a static method.

This static method calls ShowDialog on the form:

//Static method on LockWaitForm
public static LockDetails Lock(string lockedMessage, object[] params parameters)
{
        using (LockWaitForm form = new LockWaitForm(parameters))
        {
            form._lockedMessage.Text = lockedMessage;

            DialogResult result = form.ShowDialog();

            return new LockDetails (form._lockStatus, form._lock);
        }
 }

What I want is the OnLoad method of the dialog to wait up to one second before it shows, so it will only display if a lock on a record cannot be achieved after 1 second. It will happily drop out before one second if a lock is obtained before 1 second, setting its DialogResult to OK.

All functionality works fine except the hiding of the Dialog box for 1 second. All 'Visible = false' calls are ignored, and I can kind of understand why they would do that. The problem with this is that a false 'record is locked' will flash up for a sub second every time the form is used and a lock can be obtained without an issue.

I can figure out a few hacky ways to delay the visibility of the dialog box

  • Set Opacity to 0% - this does not work for Remote Desktop Connections
  • Have the form only be initialized by the static method once the 1 second has elapsed. This is promising, but requires a lot of repeated static vs non static code to handle the setup and disposal of the lock, and still feels a bit hacky.

Is it possible to limit the display of a Modal Dialog called through ShowDialog? I am reluctantly happy to PInvoke at this point (though I do want to limit non-64bit code for future requirements)

EDIT

By moving my acquire lock code to the form's constructor instead of Load, I can keep the locking code in one place, and just wait while the form's lock status is in a Waiting state before calling ShowDialog. Still feels dirty, but the cleanest method so far

+3  A: 

I would refactor the application to not even display the modal dialog until the lock process has failed to achieve a lock for one second.

Eric J.
I'm coming to the conclusion this may be the way forward, but as I said, it does require a bit of repeated code in my case
johnc
You could go with MusiGenesis' suggestion to encapsulate that logic in the current LockWaitForm by overriding ShowDialog(). That's not exactly architecturally clean, but might be a good, pragmatic solution.
Eric J.
@Eric, I agree, it nicely encapsulates the logic, and is hidden largely from the caller
johnc
+1  A: 

Not sure this would work, but: in your LockWaitForm, override ShowDialog() with your own version that calls the code to acquire a lock (or whatever it's doing), and then if more than 1 second passes, call this.ShowDialog() (the real one). This should allow you to only change the code in LockWaitForm, and not anywhere else.

Sorry, my laptop with Visual Studio is in a friend's trunk right now, so I can't check if this is possible.

MusiGenesis
Glad that worked. Now can you get my friend to answer his phone?
MusiGenesis
+1  A: 

What sort of lock? Just a normal thread lock? Can you just use Monitor.TryEnter?

If it returns false, the lock is busy and you can pop some sort of retry/cancel lock-waiting window.

If it's true though, just proceed with life as normal.

As a general comment, I really agree with Eric J that you should not be displaying the form until the lock has failed. It seems awkward to be using the error dialog to perform the ordinary workflow, and trying to secretly hide it in the non-error case.

Instead, you should have a proper workflow doing the lock entirely outside the error dialog, and pop the dialog only on the error workflow.

rice
No, the lock is a database record like lock, proprietary to our system (for many reasons I shan't go into here)
johnc
What's the API to this locking system? Do you call GetLock() and just block forever? Or do you say TryGetLock() in a loop? In the latter case it's pretty easy to keep retrying and counting the total time spent retrying, and then just pop up the window after you hit one second. In the former case, hopefully there is some kind of timeout you can define, or else you have a more difficult threading problem. Share the nature of the lock-grab call in order to get better help, I think.
rice