[英]Replacing threads with tasks
这里是线程和任务的新手:)
因此,我编写了一个简单的线程程序,该程序创建了几个线程并异步运行它们,然后等待它们完成。
然后,我将其更改为任务。 该代码做完全相同的事情,唯一的变化是我更改了两个语句。
因此,确实有两个问题:
谢谢。
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ThreadSample();
TaskSample();
}
private static void ThreadSample()
{
Random r = new Random();
MyThreadTest[] myThreads = new MyThreadTest[4];
Thread[] threads = new Thread[4];
for (int i = 0; i < 4; i++)
{
myThreads[i] = new MyThreadTest($"T{i}", r.Next(1, 500));
threads[i] = new Thread(new ThreadStart(myThreads[i].ThreadSample));
threads[i].Start();
}
for (int i = 0; i < 4; i++)
{
threads[i].Join();
}
System.Console.WriteLine("Finished");
System.Console.ReadKey();
}
private static void TaskSample()
{
Random r = new Random();
MyThreadTest[] myTasks = new MyThreadTest[4];
Task[] tasks = new Task[4];
for (int i = 0; i < 4; i++)
{
myTasks[i] = new MyThreadTest($"T{i}", r.Next(1, 500));
tasks[i] = new Task(new Action(myTasks[i].ThreadSample));
tasks[i].Start();
}
for (int i = 0; i < 4; i++)
{
tasks[i].Wait();
}
System.Console.WriteLine("Finished");
System.Console.ReadKey();
}
}
class MyThreadTest
{
private string name;
private int interval;
public MyThreadTest(string name, int interval)
{
this.name = name;
this.interval = interval;
Console.WriteLine($"Thread created: {name},{interval}");
}
public void ThreadSample()
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(interval);
Console.WriteLine($"{name} At {i} on thread {Thread.CurrentThread.ManagedThreadId}");
}
}
public void TaskSample()
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(interval);
Console.WriteLine($"{name} At {i} on thread {Thread.CurrentThread.ManagedThreadId}");
}
}
}
}
任务并行库(TPL)是一个抽象,您不应该尝试直接将任务与线程进行比较。 Task
对象代表异步任务的抽象概念-一段应该异步执行的代码,它将完成,出错(引发异常)或被取消。 抽象意味着您可以编写和使用此类任务,而不必过多地担心它们如何异步执行。 有很多有用的东西,例如ContinueWith()
,可以用来组成,排序和管理任务。
线程是一种底层系统系统工具,可用于异步运行代码,但没有从任务并行库(TPL)获得的所有好处。 如果要排序任务或类似的任务,则必须自己编写代码。
在示例代码中,您实际上并没有直接创建任何线程。 相反,您编写的Action
由系统线程池执行。 当然,可以更改。 TPL抽象层提供了可以扩展的TaskScheduler
类-如果您具有某种异步运行代码的特殊方式,则可以编写TaskScheduler
来与它一起使用TPL。
async
/ await
是100%编译器糖。 编译器将async
方法分解为块,每个块都成为Task
,并且这些块在状态机的帮助下顺序执行,所有这些都由编译器生成。 注意事项:默认情况下, await
捕获当前的SynchronizationContext
并在该上下文上恢复。 因此,如果您在WPF或Windows窗体中执行此操作,则await
后的继续代码实际上根本不在线程中运行,而是在UI线程上运行。 您可以通过调用ConfigureAwait(false)
禁用此功能。 实际上, async
/ await
主要用于在与主线程同步很重要的UI环境中进行异步编程。
- 在下面的代码中,有什么区别?
差别很大。 Task
是工作单元,它将使用线程池中的一个或多个线程,该线程是根据要计算的估计工作量分配的。 如果有另一个Task
,并且池中有暂停但仍处于活动状态的线程,而不是旋转一个新线程(这非常昂贵),而是重用已经创建的一个线程。 多个任务最终可能最终使用同一线程结束(显然不是同时发生)
简而言之,基于任务的并行性是:任务就是工作,ThreadPool提供资源来完成这些工作。 结果,更加灵活,灵活的线程/资源利用率,尤其是在针对各种执行环境和资源可用性的通用程序中,例如云上的VM。
- 我正在努力找出异步/等待。
await
暗示一项任务与另一项任务的依赖关系。 如果您没有这种情况,除了等待所有步骤完成之外,您正在做什么就足够了。 如果需要,您也可以通过TPL
来实现,例如ContinueWith
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.