2

I have a code that fetches tweets from a specific Twitter account using Tweetsharp library, creates instance of a custom UserControl and post tweet text to that UserControl then add it to a StackPanel.

However, I have to get a lot of tweets and it seems that the application would freeze while adding user controls to the StackPanel. I tried using BackgroundWorker, but I wasn't lucky until now.

My code :

private readonly BackgroundWorker worker = new BackgroundWorker();

// This ( UserControl ) is used in the MainWindow.xaml
private void UserControl_Loaded_1(object sender, RoutedEventArgs e)
{
    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.RunWorkerAsync();
}

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    int usrID;

    var service = new TwitterService(ConsumerKey, ConsumerSecret);
    service.AuthenticateWith(AccessToken, AccessTokenSecret);
    ListTweetsOnUserTimelineOptions options = new ListTweetsOnUserTimelineOptions();
    options.UserId = usrID;
    options.IncludeRts = true;
    options.Count = 10;
    twitterStatuses = service.ListTweetsOnUserTimeline(options);
}

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    try
    {
        foreach (var item in twitterStatuses)
        {
            TweetViewer tweetViewer = new TweetViewer(); // A UserControl within another UserControl
            tweetViewer.Tweet = item.Text;
            tweetViewer.Username = "@stackoverflow";
            tweetViewer.RealName = "Stack Overflow"
            tweetViewer.Avatar = ImageSourcer(item.Author.ProfileImageUrl);
            stackPanel.Children.Add(tweetViewer);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}

What I want to do now is to solve the problem of not being able to perform the code contained in worker_RunWorkerCompleted within a BackgroundWorker but every time I try to perform it using a BackgroundWorker it fails & gives me errors like :

The calling thread must be STA, because many UI components require this.

I tried also using a STA System.Threading.Thread instead of the BackgroundWorker but without luck!

What am I missing ? I'm really new to WPF and I may be ignoring something important.

Alaa Salah
  • 885
  • 1
  • 13
  • 23
  • Is your background worker methods in the MainWindow class? – ali Aug 03 '13 at 08:18
  • Can you show how you setup the `BackgroundWorker`? on which line do you get the exception? – YK1 Aug 03 '13 at 12:56
  • @ali Everything related to the **BackgroundWorker** is in another custom user control used within the _MainWindow_ class. – Alaa Salah Aug 03 '13 at 18:14
  • @YK1 Added everything into the code above. Everything within the `foreach` block seem to cause the exception. – Alaa Salah Aug 03 '13 at 18:27
  • If you're new to WPF, you might be unaware of the MVVM pattern. If you're doing WPF, you should be using MVVM. If you were using MVVM, you probably wouldn't be having this issue. – Daniel Mann Aug 03 '13 at 18:45

1 Answers1

4

You get this exception because your background worker uses a new thread, and this thread is different than the main UI thread. To simplify the error message says that you cannot change your UI element from another thread, they are independant.

This answer will solve your problem.

I also found this answer from @Marc Gravell

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files
Community
  • 1
  • 1
glautrou
  • 3,140
  • 2
  • 29
  • 34
  • 1
    According to the note on http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx it is only the DoWork handler that runs on a new thread. – Emond Aug 03 '13 at 08:34
  • @glautrou It's working, but it's the same as performing it in the `worker_RunWorkerCompleted`, the UI freezes untill everything is done. – Alaa Salah Aug 03 '13 at 18:10
  • @AlaaJoseph: If `It's working` - then how is it `the same as performing it in the worker_RunWorkerCompleted` ? You said there are exceptions in `worker_RunWorkerCompleted`!! – YK1 Aug 03 '13 at 19:48