1

I tried following:

var task = new Task(() =>
    {
       for (int i=0; i<10; i++) {
          //Create new Grid HERE
          // Add Table with some dynamic data here..
          // print the above Grid here.
        }

    });

task.ContinueWith((previousTask) =>
    {
        label.Content = printerStatus(); // will return "Out of Paper", "printing", "Paper jam", etc.
    },
    TaskScheduler.FromCurrentSynchronizationContext());

label.Content = "Sending to printer";

It returns following error: The calling thread must be STA, because many UI components require this..

The error occurs when it tries to create a new UI object Grid.

How can i fix this? Let me know if there is any other way arround!

user995387
  • 355
  • 3
  • 8
  • 17

3 Answers3

2

Tasks use thread pool threads, which are in a MTA.

If you want a background STA thread, you will have to create one yourself and explicitly set the ApartmentState.

Thread t = new Thread( ... );
t.SetApartmentState( ApartmentState.STA );
t.Start();
Nick Butler
  • 24,045
  • 4
  • 49
  • 70
  • can you show me the sample code. I am very new to this technology. – user995387 Dec 29 '11 at 11:58
  • And how can i know the task is complete using this? – user995387 Dec 29 '11 at 12:03
  • I suggest reading [Joe Albahari](http://www.albahari.com/threading/) for the basics. You have to use Threads not Tasks if you want an STA, so you don't have `ContinueWith`. You will have to use `Dispatcher.Invoke` from inside your thread method instead. – Nick Butler Dec 29 '11 at 12:19
  • @user995387 - Unless you report the progress of the thread, you have no way of knowing when the thread will be completed, thats entirely up the the scheduler. – Security Hound Dec 29 '11 at 18:43
2

You cannot create UI objects on different thread than the main UI thread because as soon as you add them to the UI, it tries to set the Parent property, and a thread in WPF cannot modify objects that were created on a different thread.

Instead, I'd recommend creating a list or collection of the Grid's Data on the 2nd thread, and binding it to the UI using something like an ItemsControl. This will keep all UI objects on the main UI thread, while background processing can be done on a background thread.

To update a UI object from a background thread, such as your status label, I'd recommend using the Dispatcher like lawrencealan's answer suggests. The Dispatcher is WPF's internal message queue for the main UI thread

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
1

Using the Dispatcher for the label and Invoke might help:

label.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Normal,
      new Action(
        delegate()
        {
          label.Content = printerStatus();
        }
    ));
Larry Williamson
  • 1,149
  • 5
  • 18
  • It is not able to create Grid! it shows error in Grid object whlie creating it. – user995387 Dec 29 '11 at 12:04
  • What do you mean by grid, you mean DataGridView or Simple Grid data structure. – crypted Dec 29 '11 at 12:19
  • WPF Grid. that holds the UI contents..msdn.microsoft.com/en-us/library/system.windows.controls.grid.aspx – user995387 Dec 29 '11 at 12:28
  • When modifying any sort of UI objects that are not created in the same thread, from within another thread or background worker, you need to use a Dispatcher. I think maybe your Grid creation is another problem, unless you are attempting to modify an existing UI object. – Larry Williamson Dec 30 '11 at 06:07
  • here is what i wanted to do: http://stackoverflow.com/questions/8671277/correct-method-of-threading – user995387 Dec 30 '11 at 08:50