3

I am very very new to WPF. I looked in the internet for several examples and tutorials about threading. They've their own way to describe. But for naive like me, I want to understand with my own style.

And I can begin my ever first Threading using database update feature.

Here is the scenario:

I have a large amount of data to insert in the database. For now let's assume the following code (this process will initiate as soon as I hit "proceed" button:

int initial = 0;
int maxData = 10
while (initial<maxData) {
   //Database query here
}

The above process will run in different thread.

Next I have a "label" in my main window. For each database query, I would like to show some message in label.

For example,

// this will happen in default UI thread.
label.Content = "Updating"; // Specifically for @TomTom ;)

EDIT: I've done the 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";

The program will return error saying "The calling thread must be STA, because many UI components require this."

I have no idea what to do next. Please help!

user995387
  • 355
  • 3
  • 8
  • 17
  • @TomTom: You are thinking too much programatically. The summary is, I want to do some heavy task in background and show it's progress in the main window. Thank you for your suggestion anyways. I actually don't want to show query update message, not even for a single query. – user995387 Dec 29 '11 at 10:18
  • Google and learn about: System.Threading.SynchronizationContext.Current. – Rick2047 Apr 23 '13 at 06:57

3 Answers3

12

You need to use the BackgroundWorker for your long running task and use Dispatcher to update UI in between

 //create background worker
 BackgroundWorker worker = new BackgroundWorker();
 //assign it work
 worker.DoWork += new DoWorkEventHandler(worker_DoWork);
 //start work
 worker.RunWorkerAsync();


//this work will be done in background
void worker_DoWork(object sender, DoWorkEventArgs e)
{
    SET initial = 0;
    SET maxData = 1000
    DO UNTIL initial <1000
   CREATE db query "INSERT INTO (col1,col2,col3) VALUES(value1,value2,value3);"

   //in between your work do this to update label
   label.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,new Action(delegate()
        {
         Label.Content = "SomeValue";
        }
        ));
   END DO
  }
Haris Hasan
  • 29,856
  • 10
  • 92
  • 122
3
  1. Multithreading hasn't anything to deal with the UI techinque you are choosing (Wpf or Winforms) - there are only slight differences when you have to switch to the UI thread to update your controls.

  2. According to your code sample, I must say, that there is no callback possibility from sql server to your program. If you want to have that feature, you have to implement the loop in C# not in a sql statement.

Edit:

According to the comment of OP I add a sample of background working and updating UI in foreground with TPL (Task Parallel Library):

var task = new Task(() =>
    {
        // Do something very long ...
    });

task.ContinueWith((previousTask) =>
    {
        label.Content = "Background work has finished.";
    },
    TaskScheduler.FromCurrentSynchronizationContext());

label.Content = "Background work is running.";
task.Start();
Fischermaen
  • 12,238
  • 2
  • 39
  • 56
  • that was just an example thought. Can you show me another way around for different scenario? For like, searching extremely large LIST with a label "searching..." and closing it when found. Any example just let me know the most basic way to do that. – user995387 Dec 29 '11 at 07:50
  • @user995387: According to your comment I've added a sample in my answer. – Fischermaen Dec 29 '11 at 08:10
  • can't i create new UI (Grid) in the task? Please read my updated query! – user995387 Dec 29 '11 at 10:33
  • @user995387: For the future please remember: for new questions, ask new questions! You get that error, because you want to create a grid in a background task, which isn't possible. You have to do it in the UI thread. But if you switch your task to the UI thread, you won't have any "multi-threading"-advantages, because then the thread is running "in the foreground". – Fischermaen Dec 29 '11 at 11:11
  • hmm ... i started new thread: http://stackoverflow.com/questions/8667529/creating-a-ui-in-background-thread-wpf can't i create a different UI thread to create a UI or flowdocument and use it in Background thread? – user995387 Dec 29 '11 at 12:20
1

Here is sample code snippet to handle WPF threading..

Consider this scenario.

we have to get some data from the server and after that we have play with data. means our next action is completely dependent on the callback or completion of Task.

in this case we can use task factory ContinueWith method like following

ObservableCollection images = new ObservableCollection();
TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
    for (int i = 0; i < 50; i++)
    {
    //GET IMAGE Path FROM SERVER
        System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
        {
        // UPDATE PROGRESS BAR IN UI
        });    
    images.Add(("");
    }

}).ContinueWith(t =>
{
    if (t.IsFaulted)
    {
        // EXCEPTION IF THREAD IS FAULT
        throw t.Exception;
    }
    System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
    {
        //PROCESS IMAGES AND DISPLAY
    });
});
horns
  • 1,843
  • 1
  • 19
  • 26
Bathineni
  • 3,436
  • 18
  • 25