Task.Run或Task.Factory.StartNew是Windows手机或任何其他客户端平台的不良做法吗?

Iva*_*lub 1 .net c# windows-phone async-await windows-runtime

我有很多使用Web服务的WP 8.1应用程序,我希望尽可能保持响应.从iOS dev expierense - 有一个严格的规则:"不要在UI线程中做任何复杂的计算!无论你如何达到这个目标:使用块或使用GCD".

问题并非所有API都具有异步版本,例如JSON.NET,SQLite或应用程序中任何自己的复杂算法.我已经阅读了很多文章,将Task.Run和Task.Factory.StartNew定义为不良做法+ 这个.

那么,编写这样的代码是否很好?它会导致一些CPU过载/电池耗尽/稳定性问题吗?如果异步包装器是个坏主意 - 什么是使复杂操作异步(背景线程)的正确方法?

 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Sri*_*vel 10

Stephen toub的文章说,为库中的同步方法公开异步包装是很糟糕的.这没有任何价值.如果开发者想要,他总是可以打电话Task.Run(()=> SomeSynchronousMethod());.无需在库中公开它.如果它是一个应用程序,是的,你可以,因为这是你可以卸载工作的唯一方法.

同样适用于"Newtonsoft.Json".因为它是一个图书馆.

Task.Run或Task.Factory.StartNew是Windows手机或任何其他客户端平台的不良做法吗?

是的,不是.

如果你有一些繁重的计算要做.说图像处理或类似的东西.无论如何你必须这样做; 它需要一些cpu周期.无论你运行什么线程,都需要一些CPU时间.这意味着你必须要消耗CPU,当然还有电池.

Task.Run或StartNew不好吗?

当你有CPU绑定工作时不是真的.这就是它们的用途.

如果你需要完成你的工作,你需要一个Thread,它不能是UI线程(我们需要它来响应).因此,使用Task.Run或StartNew借用ThreadPool线程没有错.

什么时候不好?

如果您在使用自然异步API时使用它会很糟糕.网络I/O,文件I/O等本质上是异步的.您不需要线程来调用真正的异步操作.

对IO使用线程只是通过坐下来做任何事情而浪费一个线程,直到底层设备完成IO.

简而言之,使用Task.Run进行CPU绑定,并使用自然异步API进行IO绑定操作.