Search code examples
c#.netwindows-runtimewindows-phoneasync-await

Is Task.Run or Task.Factory.StartNew are bad practice for windows phone or any other client platform?


I have WP 8.1 app that using web service a lot, and I want to keep it as much responsive as possible. From iOS dev expierense - there is one strict rule: "Do not do in UI thread any complex calculations! Doesnt matter how you will reach this: with blocks or with GCD".

Problem that not all API has async versions, e.g. JSON.NET, SQLite or any own complex algorithm in the app. I have read a lot of articles that are defining Task.Run and Task.Factory.StartNew as bad practice + this.

So, is it good to write code like this? Will it cause some cpu overloading/battery drain/stability issues? If async wrappers are bad idea - what is the right way to make complex operations async(background thread)?

 protected async Task<T> GetDataAsync<T>(string uriString, CancellationToken cancellationToken = default(CancellationToken))
    {
        var uriToLoad = new Uri(uriString);
        using (var httpClient = new HttpClient())
        {
            var response= await httpClient.GetAsync(uriToLoad, cancellationToken).ConfigureAwait(false);
            response.EnsureSuccessStatusCode();
            cancellationToken.ThrowIfCancellationRequested();

            var dataString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            cancellationToken.ThrowIfCancellationRequested();

            // async wrapped call to sync API
            var result = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(dataString), cancellationToken).ConfigureAwait(false);
            cancellationToken.ThrowIfCancellationRequested();

            return result;
        }
    }

Solution

  • Stephen toub's article says that exposing asynchronous wrappers for synchronous methods in a library is bad. That adds no value. If the developer wants, he can always call Task.Run(()=> SomeSynchronousMethod());. There is no need to expose it in a library. If it is an application, yes you can, because that is the only way you can off load the work.

    Same applies to "Newtonsoft.Json". because it is a library.

    Is Task.Run or Task.Factory.StartNew a bad practice for windows phone or any other client platform?

    Yes and no.

    If you have some heavy computation to do. Say image processing or something like that. You'll anyway have to do it; It needs some cpu cycles. No matter what thread you run, it will need some amount of cpu time. Which means that you must have to consume the cpu and of course battery.

    Is Task.Run or StartNew bad?

    Not really when you have CPU bound work. That's what they are for.

    If you need to get your work done, you need a Thread, it can't be UI thread(we need it to be responsive). So, nothing wrong in borrowing a ThreadPool thread using Task.Run or StartNew .

    When it is bad?

    It is bad if you're using it when you can use naturally asynchronous API. Network I/O, File I/O etc are inherently asynchronous. You don't need a thread to invoke truly asynchronous operation.

    Using threads for IO is just wasting a thread by sitting and doing nothing till the underlying device to completes the IO.

    In short use Task.Run for CPU bound and naturally asynchronous API for IO bound operations.