0

When my main form loads I want to do some processing like loading the last client viewed. This extra processing causing the drawing of the form to be pretty ugly. I am doing it on form shown so I would expect that the form would be done painting.

I have used PostMessage... Is there a modern day version of PostMessage? During this processing I would like to set the hourglass cursor.

Gina Marano
  • 1,773
  • 4
  • 22
  • 42
  • 2
    What do you exactly mean by "causing the drawing of the form to be pretty ugly"? Does the form turn into a horrific demon or does it go into `Not Responding` state or is it something else? – Arian Motamedi May 10 '13 at 17:26
  • 1
    If you want to perform a long running task that won't be manipulating the user interface your best bet would probably be the `BackgroundWorker` class in C# 4.0. – Servy May 10 '13 at 17:28
  • 1
    If you want a long running task that *does* manipulate the user interface, your best bet is *still* probably BackgroundWorker (and BeginInvoke'ing to update the UI when you want to.) In this case, you would probably want to set the form to appear and act disabled, start your BackgroundWorker, then set the form enabled again in the RunWorkerCompleted event. – neminem May 10 '13 at 17:33
  • programmer93: the painting of the form doesn't look complete. – Gina Marano May 10 '13 at 19:20

3 Answers3

4

I think what you are trying to do is background processing. So you can use a BackgroundWorker class. When your form loads, you would start the background worker and when the worker is finished, it will notify your form through the RunWorkerCompleted event. You can even get progress updates from the worker by implementing ProgressChanged event.

Tombala
  • 1,660
  • 9
  • 11
1

How about using Task + ContinueWith. (If you upgrade to .Net 4.5 async/await would be a better choice).

private void Form_Load(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
        {
            Thread.Sleep(5000); //Some long Running Jobs
            return "Finished";
        })
        .ContinueWith(t =>
            {
                this.Text = t.Result; //Update GUI
            },
            TaskScheduler.FromCurrentSynchronizationContext());

}
I4V
  • 34,891
  • 6
  • 67
  • 79
  • I like this answer because it is outside the box and I learned something new. I expected to be told to use a thread. This alternative didn't save me very much work since I still had to do InvokeRequired/Invoke. It keeps the code compact and clean. Above task.factory... I used "this.Cursor = Cursors.WaitCursor;" and in the ContinueWith I used "this.Cursor = Cursors.Default;". – Gina Marano May 10 '13 at 19:49
  • @ginalster **a)** `I expected to be told to use a thread`, Tasks are not much different than threads, in fact, they use threads internally. **b)** `since I still had to do InvokeRequired/Invoke`, No you don't need to use it in `ContinueWith` block. This is why I used `TaskScheduler.FromCurrentSynchronizationContext()`. Just return the data required for GUI in `StartNew` block and use it in `ContinueWith` – I4V May 10 '13 at 19:51
  • a) agreed b) obviously you are correct. I didn't have to (InvokeRequired/Invoke) but I am using a common method and I don't want to duplicate code. – Gina Marano May 10 '13 at 21:15
0

I am not sure why would you want to use PostMessage. If you post a message using PostMessage it will eventually be obtained by GetMessage and unless the message is posted from a different thread whole exercise seems a little futile. Am I missing something here? As for BackgroundWorker please refer to the solution for Label is not set until method is done.

Community
  • 1
  • 1
Abhinav
  • 2,085
  • 1
  • 18
  • 31
  • yes, it isn't the best way but appears to work. PostMessage put the message on the queue and immediately returns and FormShown can continue. I am looking for a better way so no need to discuss it. – Gina Marano May 10 '13 at 18:30