8

Possible Duplicate:
How to create a task (TPL) running a STA thread?

I'm using the following code:

var task = Task.Factory.StartNew<List<NewTwitterStatus>>(
        () => GetTweets(securityKeys),  
        TaskCreationOptions.LongRunning);

Dispatcher.BeginInvoke(DispatcherPriority.Background,
    new Action(() =>
    {
        var result = task.Result; // ERROR!!! The calling thread cannot access this object because a different thread owns it.
        RecentTweetList.ItemsSource = result;
        Visibility = result.Any() ? Visibility.Visible : Visibility.Hidden;
    }));

And I'm getting the error:

var result = task.Result; // ERROR!!! The calling thread cannot access this object because a different thread owns it.

What do I need to do to resolve this problem?

Community
  • 1
  • 1
NoWar
  • 36,338
  • 80
  • 323
  • 498
  • Keep in mind that `Task.Result` will block until the result is available, so if this code didn't error then you'd be blocking the UI thread while you waited for the task to finish; that would be bad. You need to wait to invoke the UI thread until you actually have the result. – Servy Oct 29 '12 at 15:44

3 Answers3

16

The idea of Tasks is that you can chain them:

  var task = Task.Factory.StartNew<List<NewTwitterStatus>>(
                            () => GetTweets(securityKeys),  
                            TaskCreationOptions.LongRunning
                        )
        .ContinueWith(tsk => EndTweets(tsk) );


    void EndTweets(Task<List<string>> tsk)
    {
        var strings = tsk.Result;
        // now you have your result, Dispatchar Invoke it to the Main thread
    }
dtb
  • 213,145
  • 36
  • 401
  • 431
H H
  • 263,252
  • 30
  • 330
  • 514
1

You need to move the Dispatcher call into the task continuation which would look something like this:

var task = Task.Factory
    .StartNew<List<NewTwitterStatus>>(() => GetTweets(securityKeys), TaskCreationOptions.LongRunning)
    .ContinueWith<List<NewTwitterStatus>>(t =>
    {
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
            new Action(() =>
            {
                var result = t.Result;
                RecentTweetList.ItemsSource = result;
                Visibility = result.Any() ? Visibility.Visible : Visibility.Hidden;
            }));
    },
    CancellationToken.None,
    TaskContinuationOptions.None);
Trevor Pilley
  • 16,156
  • 5
  • 44
  • 60
1

It looks like you are starting a background task to start reading tweets, then starting another task to read the result without any co-ordination between the two.

I would expect your task to have another task in a continuation (see http://msdn.microsoft.com/en-us/library/dd537609.aspx) and in the continuation you may need to invoke back to the UI thread....

var getTask = Task.Factory.StartNew(...);
var analyseTask = Task.Factory.StartNew<...>(
()=> 
Dispatcher.Invoke(RecentTweetList.ItemsSource = getTask.Result));
AlSki
  • 6,868
  • 1
  • 26
  • 39