Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event on Task Result is done [duplicate]

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?

like image 426
Friend Avatar asked Oct 29 '12 15:10

Friend


People also ask

What is the use of events in Task Scheduler?

Task Scheduler successfully finished the "%3" instance of the "%1" task for user "%2". This event is logged when the task scheduler successfully finished the instances of the task user and the history of a task is tracked by events. This is an information event and no user action is required.

Are recurring tasks creating duplicate entries?

I reached out to Microsoft To Do Support on November 25th, 2019 and received the following response on November 26th, 2019: Thank you for letting us know about this. Our apologies for the trouble. We're aware of this issue and are working on a fix. A lot of other users also reported that recurring tasks are creating duplicate entries.

Why can’t I call setresult from taskcompletionsource?

The issue may occur when “a continuation” (*) of a task, backed by TaskCompletionSource<T>, blocks the thread in one way or another, thereby blocking a thread that calls SetResult. (*) As we’ll see in a moment different types of continuations behave differently. The main challenge with such issues that it’s very hard to understand the root cause.

How to create a task and run it asynchronously?

If you can’t control a task’s creation but want to run the continuations asynchronously you can explicitly call Task.Yield()right after awaitor switch to custom tasks altogether (which is hardly an option). But if you can, you should provide task creation options every time you use TaskCompletionSource<T>:


3 Answers

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
    }
like image 72
Henk Holterman Avatar answered Oct 02 '22 16:10

Henk Holterman


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);
like image 39
Trevor Pilley Avatar answered Oct 02 '22 16:10

Trevor Pilley


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));
like image 24
AlSki Avatar answered Oct 02 '22 18:10

AlSki