4

I want a webrequest running in a background thread, and then for the callback to be handled in the UI thread. Here is my code:

Task.Factory.StartNew(() =>
    {
        Console.Out.WriteLine("Start the request");
        return request.GetResponse();
    }
    ).ContinueWith(t =>
    {
        Console.Out.WriteLine("Response");
        using (HttpWebResponse response = (HttpWebResponse)t.Result)
        {
            string responseBody = ...
        }
    },
    TaskScheduler.FromCurrentSynchronizationContext());

    Console.Out.WriteLine("Continue with normal UI code");
}

What should happen:

"Start the request"
"Continue with normal UI code"
.
. 
.
"Response"

But I get:

"Start the request"
.
.
.
"Response"
"Continue with normal UI code"

It's like request.GetResponse() stops the entire thread independent of StartNew. Any ideas? I am using MonoDevelop (Mono for Android).

Edit: According to Mono for Android documentation

"Tasks created with the Parallel Task Library can run asynchronously and return on their calling thread, making them very useful for triggering long-running operations without blocking the user interface.

A simple parallel task operation might look like this:"

using System.Threading.Tasks;
void MainThreadMethod ()
{
    Task.Factory.StartNew (() => wc.DownloadString ("http://...")).ContinueWith (
        t => label.Text = t.Result, TaskScheduler.FromCurrentSynchronizationContext()
    );
}

So my solution should work!

If anyone have a better way of doing background call + UI-thread-callback I'm open to suggestions. Tried BeginGetResponse / EndGetResponse but the callback where not run on the UI thread.

poupou
  • 43,413
  • 6
  • 77
  • 174
Sunkas
  • 9,542
  • 6
  • 62
  • 102
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Feb 20 '13 at 16:51

1 Answers1

3

Task.Factory.StartNew() doesn't start a new thread per se, it instead allows the method entry point to be called again without being blocked while it hands the current method call. How this happens under the hood is a little complex but using it is not a "start a new thread and run this code" approach. On top of that, there is no reason why the cpu wouldn't decide to run the code within a Thread before exiting on the calling thread. It's up to the thread scheduler.

DiskJunky
  • 4,750
  • 3
  • 37
  • 66
  • According to http://docs.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_5_-_practical_code_sharing_strategies "Tasks created with the Parallel Task Library can run asynchronously and return on their calling thread, making them very useful for triggering long-running operations without blocking the user interface" – Sunkas Feb 20 '13 at 16:23
  • 1
    @Sunkas The key word there is **can**, as opposed to **will**. You should really use the asynchronous method of getting the response though, rather than using the synchronous method and trying to put it in a background thread. – Servy Feb 20 '13 at 16:30
  • @Sunkas yes, **can** run. See http://byterot.blogspot.ie/2012/04/aspnet-web-api-series-part-3-async-deep.html. It says "it does not necessarily mean a Task will run on a background thread or in the ThreadPool.". – DiskJunky Feb 20 '13 at 16:30
  • Ok, thanks! Had a asynchronous solution but the callback I got for it was ran on the background thread. Any leads on how to make it run on the UI thread to be able to update the UI ? – Sunkas Feb 20 '13 at 16:34
  • 1
    @Sunkas try the following: http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – DiskJunky Feb 20 '13 at 16:37