0

I have a working app that adds new a new RibbonTab and a new child control to the Grid.

I would like to put this action onto a background thread as the child control can take a while to gather data from a database, etc.

I have the following code so far:

Ribbon Ribbon_Main = new Ribbon();
Grid Grid_Main = new Grid();

Thread newthread2 = new Thread(new ThreadStart(delegate { Graphing_Template.add_report(); }));
newthread2.SetApartmentState(ApartmentState.STA);  //Is this required?
newthread2.Start();


Class Graphing_Template()
{
  static void add_report()
   {
     RibbonTab rt1 = new RibbonTab();
     MainWindow.Ribbon_Main.Items.Add(rt1);
     // Create control with information from Database, etc.
     // add control to MainWindow.Grid_Main
   }
}

I would like the new report control to be created in the background and then added to the Main UI when it is ready.

The solution I went with is:

     BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                DataTable dt1 = new DataTable();
               ---- Fill DataTable with
                args.Result = datagrid_adventureworks_DT();
            };

 worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
            {
                DataTable dt1 = (DataTable)args.Result;
                Datagrid_Main.ItemsSource = dt1.AsDataView();
            };
11
  • As a general rule, don't touch UI objects unless you're on the UI thread. Do the grunt work in a background thread, sure, but then marshal the UI updates to the UI thread via the dispatcher. Commented Mar 24, 2014 at 20:47
  • Could I generate the two child objects and then pass them back to the UI thread? Commented Mar 24, 2014 at 20:50
  • I don't know enough WPF to give a definitive answer, sorry. I suspect it would work, but I know it wouldn't with winforms, for example, because Win32 UI objects must be touched only by the thread that creates them (WPF doesn't use Win32 UI objects for simple things like buttons, etc.). Commented Mar 24, 2014 at 21:28
  • @user3329538 What do you need to do this in the first place? You are just creating an instance of an object. There's no need to put these two on a different thread. In fact, creating a new thread might actually take longer than just creating a Ribbon and a Grid object on the caller thread. Commented Mar 24, 2014 at 21:32
  • 1
    If your posted code is representative of what you'll be doing (some side work and a quick update to the UI), I'd recommend taking a look at the BackgroundWorker class. It fires off a thread with an in-built mechanism to communicate with the original thread. If you're doing anything more complex, though, Task is going to be a better choice. Commented Mar 24, 2014 at 23:00

1 Answer 1

1
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Test4();

    }
    private void Test1()
    {
        while (true)
        {
            this.Title = DateTime.Now.ToString();
            System.Threading.Thread.Sleep(5000); //locks up app
        }
    }
    private void Test2()
    {
        var thd = new System.Threading.Thread(() => {
            while (true)
            {
                this.Title = DateTime.Now.ToString(); //exception
                System.Threading.Thread.Sleep(5000);
            }            
        });
        thd.Start();
    }

    private void Test3()
    {   //do the work on the background thread
        var thd = new System.Threading.Thread(() =>
        {
            while (true)
            {   //use dispatcher to manipulate the UI
                this.Dispatcher.BeginInvoke((Action)(() 
                    => { this.Title = DateTime.Now.ToString(); 
                }));

                System.Threading.Thread.Sleep(5000);

                //there's nothing to ever stop this thread!
            }
        });
        thd.Start();
    }

    private async void Test4()
    {   //if you are using .Net 4.5 you can use the Async keyword
        //I _think_ any computation in your async method runs on the UI thread, 
        //so don't use this for ray tracing, 
        //but for DB or network access your workstation can get on with 
        //other (UI) work whilst it's waiting
        while (true)
        {
            await Task.Run(() => { System.Threading.Thread.Sleep(5000); });
            this.Title = DateTime.Now.ToString();
        }
    }
Sign up to request clarification or add additional context in comments.

1 Comment

I need to do some further testing on Test3... as I am running into some issues. Will clarify later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.