我可以将'Task.Run'更改为'async void'吗? (Xamarin.forms)

时间:2017-03-01 12:52:55

标签: c# multithreading xamarin xamarin.forms

我正在使用XF pcl制作应用程序。即使我已经在商店推出了我的应用程序,我仍然是c#world的新手。我特别使用线程时遇到了麻烦。

在XF / iOS中,我在启动app后花了一段时间(超过一天),我的代码的所有Task.Run()都没有启动新线程。一个人告诉我,如果我有可能开始很多线程,不知何故他们没有被终止。所以新线程没有开始。

所以我搜索了我的项目,我的代码中有大约20个位置的Task.Run。

我在调用'async Task'方法时使用它,即使它不需要后台线程。

所以,我打算使用'async void'来改变它。但我已经这样改变了。没问题。

  

让我们说AAAAA()是我正在使用的一些nuget库的'异步任务'方法。所以   我无法改变方法。

void Something() 
{
...
    Task.Run(async () => await XXXXX.AAAAA());
...
}

async void Something() 
{
...
 await XXXXX.AAAAA();
...
}

但有时,我遇到了我无法轻易改变异步方法。所以我当时就会这样改变。

void Something() 
{
...
 AA();
...
}

async void AA() 
{
await XXXXX.AAAAA();
}

除非没有后台线程,否则这样可以吗?

我问这个问题是因为我看了很多视频,说不要使用“Async void”。

我想知道如果没有问题我是否可以这样使用。

任何建议都会对我有所帮助。 感谢。

1 个答案:

答案 0 :(得分:5)

不要执行async void。关于它有几个worst practices

相反,尝试通过良好的异步编程方法从根本位解决线程问题。

1。定义任务边界

不要只是“开火而忘记”。期望您的任务结束并释放资源。有很好的理由来做Task.Run(...)并忘掉它。

异步方法存在是有原因的。它们返回Future(引用Java世界)。如果你解雇过多的异步任务需要很长时间才能完成或陷入循环,你就会耗尽系统资源,最终可能无法产生新的任务。

所以分析你的问题,不要只是从随机包中运行随机方法。设计您的工作流程并识别并行性。

一个简单直接的解决方案是Task.Run(()=>).Wait()。这会破坏各种并行性,但会限制资源,最重要的是,它会遵循同步编程。

2。任务不是线程

虽然我不鼓励无限制/不受控制地使用线程,但事实是Task.Run(...)不一定会产生新线程。在某些情况下,它实际上可能无法做任何事情。

例如,我被迫这样做以强制开始一个新线程

Task.Factory.StartNew(()=>..., cancellationToken: tokenSource.Token, creationOptions:
                                            TaskCreationOptions.LongRunning, scheduler: TaskScheduler.Default);

TaskCreationOptions.LongRunning告诉Task工厂使用可用的单独线程。通常,Task.Run通过利用VM等待从其他任务运行代码来在同一当前线程上运行,以便执行轻量级上下文切换。如果同步代码以同步方式阻塞,则运行时可能无法控制其他任务。

3。 TPL是为2件事做的

一个是响应性。如果您的应用程序完全异步,那么充分利用TPL会使您的UI线程在等待时响应,例如:如果你点击一个按钮,你将看不到整个窗口变灰并“卡住”。 Microsoft已引入此行为,以帮助对正确的多线程编程不友好的开发人员

另一个是 I / O优化。如果你需要下载5个文件,从磁盘解析文本文件并在数据库中存储一堆行,你可以激活7个任务,利用每个任务的I / O等待时间(例如SSL握手,磁盘缓冲,SQL响应等待)这样,7个任务将在最长的时间内合理地完成。

如果您只是因为在NuGet库中找到异步方法而调用异步方法,那么您只是做错了,因为您可能需要调用相应的同步版本

综述

您的问题表明对并行编程缺乏了解。事实上,你说你是C#的新手。欢迎来到.NET世界。

并行编程并不容易,如果不了解您的应用程序设计,就无法在一个简短的答案中帮助您。您需要通过发布真实或类似的实际代码,为应用程序的某些部分提供几个示例和/或询问有关特定最佳实践的问题。