MoonKnight
MoonKnight

Reputation: 23831

Forcing a Task to Wait Before Updating the UI in Continuation

All, I want to update a ToolStripMenu to show an SqlConnection failure. I want the error message to display for some time timeToWaitMs (in milli-second) and then refresh the UI back to an okay state after some time and some operations. Currently I am doing (with some un-necessary details removed)

public void ShowErrorWithReturnTimer(string errorMessage, int timeToWaitMs = 5000)
{
    // Update the UI (and images/colors etc.).
    this.toolStripLabelState.Text = errorMessage;

    // Wait for timeToWait and return to the default UI.
    Task task = null;
    task = Task.Factory.StartNew(() =>
        {
            task.Wait(timeToWaitMs);
        });

    // Update the UI returning to the valid connection.
    task.ContinueWith(ant =>
        {
            try
            {
                // Connection good to go (retore valid connection update UI etc.)!
                this.toolStripLabelState.Text = "Connected";
            }
            finally
            {
                RefreshDatabaseStructure();
                task.Dispose();
            }
        }, CancellationToken.None,
            TaskContinuationOptions.None,
            mainUiScheduler);
}

The problem I have is that task.Wait(timeToWaitMs); is causing a Cursors.WaitCursor to be displayed - I don't want this. How can I force the error message to be displayed for a period, after which I return to a non-error state?

Thanks for your time.

Upvotes: 1

Views: 509

Answers (2)

margabit
margabit

Reputation: 2954

You can use a Timer, instead of task.Wait().You can make it wait for an amount of time. Once the timer ticks, a callback can start the update.

var timer = new Timer(timeToWaitMs);
timer.Elapsed += (s, e) =>
                              {
                                  timer.Stop();
                                  UpdateValidConnection();
                              };



private void UpdateValidConnection()
{
    Task.Factory.StartNew(() =>
    {
        try             
        {
            this.toolStripLabelState.Text = "Connected";
        }
        finally
        {
            RefreshDatabaseStructure();
        }
    }, CancellationToken.None, TaskCreationOptions.None, mainUiScheduler);
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1504062

I wouldn't use a task at all here - at least not without the async features in C# 5. In C# 5 you could just write:

await Task.Delay(millisToWait);

But until you've got that, I'd just use a timer appropriate for your UI, e.g. System.Windows.Forms.Timer or System.Windows.Threading.DispatcherTimer. Just use what you've currently got as a continuation as the "tick" handler for the timer, and schedule it appropriately.

Upvotes: 5

Related Questions