用任务

时间:2018-06-15 19:14:25

标签: c# .net

此处新线程和任务:)

所以,我编写了一个简单的线程程序,它创建了几个线程并异步运行它们然后等待它们完成。

然后我将其更改为任务。代码完全相同,唯一的变化是我改变了几个语句。

所以,真的有两个问题:

  1. 在下面的代码中,有什么区别?
  2. 我正在努力找出异步/等待。我如何将它集成到下面,或者给出所有示例似乎是一个方法调用另一个async / await返回这是一个使用Task做后台工作的坏例子?
  3. 感谢。

        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}");
                        }
                    }
                }
        }
    

2 个答案:

答案 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)

  
      
  1. 在下面的代码中,有什么区别?
  2.   

差异很大。 Task是一个工作单元,它将使用根据要计算的估计工作量分配的线程池中的线程。如果还有另一个Task,并且池中有暂停但仍然存在的线程,而不是旋转新线程(这非常有用),它会重用已经创建的线程。多个任务最终可能最终使用相同的线程(非同时显然)

基于任务的并行性简而言之:任务是工作,ThreadPool提供资源来完成这些工作。后果,更聪明,更有弹性的线程/资源利用率,尤其是针对各种执行环境和资源可用性的通用程序,例如云上的VM。

  
      
  1. 我正在努力找出异步/等待。
  2.   

await暗示一个任务与另一个任务的依赖关系。如果在你的情况下你没有它,除了等待所有它们完成之外,你在做什么就足够了。 如果需要,您也可以使用TPL来实现,例如ContinueWith