H W
H W

Reputation: 2596

Simulate async/await with task.continuewith in .net 4.0

Is it possible to simulate the behaviour of async/await in .NET 4.0 without using the Microsoft.Bcl.Async Package?

I tried running

Task myTask = Task.Factory.Startnew(MyMethod,...)
myTask.ContinueWith((x)=>{
    //do stuff when myTask is completed
},...);
//code that i hoped would run without waiting for myTask

but this blocks my UI while myTask is running. When searching for this issue, i found this question which seems to ask the exact same thing and even presents a solution with a full code sample. However when i tried calling GetResponseWithRetryAsync (or running it with task.Start(), or wrapping it in Task.Factory.StartNew()) it still blocks my UI thread. Why are all these ways of running a task blocking my UI?

edit: sample code which blocks my UI as requested by user1

Task myTask = Task.Factory.StartNew(MyMethod, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
myTask.ContinueWith((x) =>
    { 
     this.Title="Done!";
    }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());

where MyMethod is

    public void MyMethod(){
        WebRequest request = WebRequest.Create("http://google.com/");
        request.Credentials = CredentialCache.DefaultCredentials;
        WebResponse response = request.GetResponse();
        Stream dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);

        string responseFromServer = reader.ReadToEnd();
        Console.WriteLine(responseFromServer);
        reader.Close();
        response.Close();
    }

Upvotes: 1

Views: 2449

Answers (2)

JKennedy
JKennedy

Reputation: 18827

Task myTask = Task.Factory.Startnew(MyMethod)
myTask.ContinueWith((x)=>
{
    //do stuff when myTask is completed
},new CancellationToken(),TaskContinuationOptions.OnlyOnRanToCompletion,TaskScheduler.FromCurrentSynchronizationContext());

This means that the continue with wont block your UI thread. The main thing here is TaskScheduler.FromCurrentSynchronisationContext()

Upvotes: 1

i3arnon
i3arnon

Reputation: 116636

It is possible to imitate async-await without the compiler and framework's help, although extremely difficult to get right. You need to take care of capturing context, exception handling, returning a result and so forth.

The cases you mentioned aren't supposed to block the UI throughout the asynchronous operation. However there may be some synchronous work being done before the asynchronous operation like DNS resolution. If that's the case, use Task.Run and offload that work to a ThreadPool thread to improve responsiveness.

Upvotes: 3

Related Questions