此处新线程和任务:)
所以,我编写了一个简单的线程程序,它创建了几个线程并异步运行它们然后等待它们完成。
然后我将其更改为任务。代码完全相同,唯一的变化是我改变了几个语句。
所以,真的有两个问题:
感谢。
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}");
}
}
}
}
答案 0 :(得分:3)
任务并行库(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环境中的异步编程。
答案 1 :(得分:1)
- 在下面的代码中,有什么区别?
醇>
差异很大。 Task
是一个工作单元,它将使用根据要计算的估计工作量分配的线程池中的线程。如果还有另一个Task
,并且池中有暂停但仍然存在的线程,而不是旋转新线程(这非常有用),它会重用已经创建的线程。多个任务最终可能最终使用相同的线程(非同时显然)
基于任务的并行性简而言之:任务是工作,ThreadPool提供资源来完成这些工作。后果,更聪明,更有弹性的线程/资源利用率,尤其是针对各种执行环境和资源可用性的通用程序,例如云上的VM。
- 我正在努力找出异步/等待。
醇>
await
暗示一个任务与另一个任务的依赖关系。如果在你的情况下你没有它,除了等待所有它们完成之外,你在做什么就足够了。
如果需要,您也可以使用TPL
来实现,例如ContinueWith