简体   繁体   English

我可以将“ Task.Run”更改为“异步无效”吗? (Xamarin.forms)

[英]Can I change 'Task.Run' to 'async void'? (Xamarin.forms)

I'm making app with using XF pcl. 我正在使用XF pcl制作应用程序。 Even I launched my app on the store already, I'm still newbie in c# world. 即使我已经在商店中启动了我的应用程序,我仍然是C#世界中的新手。 I'm having a trouble especially using a Thread. 我在使用线程时遇到了麻烦。

In XF/iOS, I faced after I launched app and took a while(longer than a day), all of Task.Run() of my code does not start new thread. 在XF / iOS中,启动应用程序并花了一段时间(超过一天)之后,我的代码的所有Task.Run()都没有启动新线程。 A person advised me if there is a chance that I'm starting many thread and somehow they are not terminated. 一个人告诉我,是否有可能我正在启动多个线程,并且某种程度上它们不会终止。 So new thread's not started. 因此,新线程尚未启动。

So I searched my project and I have Task.Run at about 20 places in my code. 因此,我搜索了我的项目,并在代码中的大约20个地方有了Task.Run。

I used it when I call 'async Task' method even it background thread is not necessary. 我在调用“异步任务”方法时使用了它,即使不需要后台线程也是如此。

So, I'm going to change it by using 'async void'. 因此,我将使用“异步无效”来更改它。 But I already changed it like this. 但是我已经这样改变了。 and no problem. 没问题

Let's say AAAAA() is a 'async Task' method from some nuget library I'm using. 假设AAAAA()是我正在使用的某些nuget库中的“异步任务”方法。 So I can not change method. 所以我不能改变方法。

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

to

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

But sometimes, I faced that I can't change a method to async easily. 但是有时候,我面临着无法更改异步方法的麻烦。 So I'm going to change like this at that time. 所以那时我要这样改变。

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

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

Is this OK unless background thread is not necessary? 除非不需要后台线程,否则可以吗?

I ask this question because I watched lots of videos that saying not to use "Async void". 我问这个问题是因为我看了很多视频,说不要使用“异步无效”。

I wonder if I could use like this if there seems no problem. 我想知道如果似乎没有问题,我是否可以使用这种方式。

Any advice will help me. 任何建议都会对我有帮助。 Thanks. 谢谢。

Don't do async void . 不要async void There are several worst practices about it. 有几种最坏的做法

Instead, try to solve your threading problems from the root with a good approach to asynchronous programming. 相反,请尝试从根本上解决异步处理的线程问题。

1. Define your task boundaries 1.定义任务边界

Do not just "fire and forget". 不要只是“生与死”。 Expect your task to end and release resources. 期望您的任务结束并释放资源。 There are good reasons not to do Task.Run(...) and forget about it. 有充分的理由执行Task.Run(...)而忘记它。

Async methods exist for a reason. 存在异步方法是有原因的。 They return in the Future (to quote the Java world). 他们在Future返回(引用Java世界)。 If you fire too many Async task that take long time to complete or get stuck in a loop, you drain your system resources and may end up unable to spawn new tasks. 如果您触发了太多的异步任务,这些任务花费很长时间才能完成或陷入循环中,则会耗尽系统资源,并最终导致无法生成新任务。

So analyze your prolem, don't just run random methods from random packages. 因此,分析您的问题,不要只是从随机程序包中运行随机方法。 Design your workflow and identify parallelisms. 设计您的工作流程并确定并行性。

A simple straightforward solution is to Task.Run(()=>).Wait() . 一个简单而直接的解决方案是Task.Run(()=>).Wait() This destroys all kinds of parallelism but will constrain the resources and, most importantly, adheres with your synchronous programming. 这破坏了所有的并行性,但是会限制资源,最重要的是,坚持您的同步编程。

2. A Task is not a Thread 2.任务不是线程

While I discourage the unbounded/uncontrolled use of threads, the truth is that Task.Run(...) won't necessarily spawn new threads. 尽管我不鼓励无限制/不受控制地使用线程,但事实是Task.Run(...)不一定会产生新线程。 It may not actually do anything under some circumstances. 在某些情况下,它实际上可能没有任何作用。

For example I was forced to do this to force starting a new thread 例如,我被迫这样做以强制启动新线程

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

TaskCreationOptions.LongRunning tells the Task factory to use an available separate thread. TaskCreationOptions.LongRunning告诉Task工厂使用可用的单独线程。 Normally Task.Run runs on the same current thread by exploiting VM waits to run code from other tasks, so as to perform a lightweight context switch. 通常, Task.Run通过利用VM等待运行其他任务的代码来在同一当前线程上运行,从而执行轻量级上下文切换。 If your synchronous code blocks in a synchronous way the runtime may not give control to other tasks. 如果您的同步代码以同步方式阻塞,则运行时可能无法控制其他任务。

3. TPL is made for 2 things 3. TPL是为两件事情制作的

One is responsiveness . 一种是响应能力 If your application is completely asynchronous, then a good use of the TPL leaves your UI thread responsive over waits, eg if you click on a button you won't see the whole window greyed and "stuck". 如果您的应用程序是完全异步的,那么对TPL的良好使用将使UI线程在等待时保持响应,例如,如果您单击按钮,您将看不到整个窗口变灰和“卡住”。 This behaviour was introduced by Microsoft to help developers that are unfriendly with proper multithread programming Microsoft引入此行为是为了帮助对正确的多线程编程不友好的开发人员

The other is I/O optimization . 另一个是I / O优化 If you need to download 5 files, parse a text file from disk and store a bunch of rows in the database you can fire 7 task that leverage the I/O wait times of each task (eg SSL handshake, disk buffering, SQL response wait) so that the 7 tasks will reasonably complete by the time of the longest. 如果您需要下载5个文件,从磁盘解析一个文本文件并在数据库中存储一堆行,则可以触发7个任务,这些任务利用每个任务的I / O等待时间(例如SSL握手,磁盘缓冲,SQL响应等待) ),以便在最长的时间内合理地完成这7个任务。

If you just invoke asynchronous methods because you found them on your NuGet library you are just doing it wrong, as you may need to invoke the corresponding synchronous version 如果由于在NuGet库中找到异步方法而仅调用异步方法,则说明这样做是错误的,因为您可能需要调用相应的同步版本

Summarizing 总结

Your question reveals a lack of understanding of parallel programming. 您的问题表明对并行编程缺乏了解。 In fact you said you are new to C#. 实际上,您说过您是C#的新手。 Welcome to the world of .NET. 欢迎来到.NET的世界。

Parallel programming is not easy, and without a knowledge of your application design it is impossible to help you in a single short answer. 并行编程并不容易,而且如果不了解您的应用程序设计,就不可能在一个简短的答案中为您提供帮助。 You need to take several examples and/or ask questions about specific best practice for some parts of your application by posting real or simil-real code. 您需要举几个例子和/或通过发布真实或类似真实的代码来询问有关应用程序某些部分的特定最佳实践的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM