文档章节

C# 多线程、异步线程、线程池相关知识

深圳大道
 深圳大道
发布于 2016/12/29 15:25
字数 1317
阅读 12
收藏 0
/*
线程池ThreadPool类会在需要时增减池中线程的线程数,直到最大的线程数。池中的最大线程数是可配置的。
在双核CPU中,默认设置为1023个工作线程和1000个I/O线程。也可以指定在创建线程池时应立即启动的最小线程数,
以及线程池,中可用的最大线程数。如果有更多的作业要处理,线程池中线程的个数也到了极限,
最新的作业就要排队,且必须等待线程完成其任务。
*/

//下面这个方法是一个符合WaitCallBack委托的方法:
static void WaitCallBackMethod(object param)
{
     for (int i = 0; i < 5; i++)
     {
         Console.WriteLine(String.Format("Thread {0} is running", param));
         Thread.Sleep(1000);
     }
}
//然后在主线程里给线程池添加方法,QueueUserWorkItem()方法的第二个参数是个object类型的参数,可传入一个数据到线程中

static void Main(string[] args)
{
     for (int i = 1; i <= 3; i++)
     {
         ThreadPool.QueueUserWorkItem(WaitCallBackMethod, i);
     }
     Console.Read();
}

/////////////////////////////////////////////////////////////////
//Task任务
1、Task类构造函数

使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。
接着调用Task类的Start()方法来启动任务。
使用Task类时,除了调用Start()方法,还可以调用RunSynchronously()方法。
这样,任务也会启动,但是同时调用。默认情况下,任务是异步运行的。
Task类的构造函数接收一个无参无返回值的委托:

Task task = new Task(TaskMethod);
task.Start();

下面是TaskMethod方法:
static void TaskMethod()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(String.Format("Running in a task. Task ID: {0}", Task.CurrentId));
        Thread.Sleep(500);
    }
}

方法里用Task.CurrentId属性取得当前任务ID。下面是主线程:
static void Main(string[] args)
{
    Task task = new Task(TaskMethod);
    task.Start();
 
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("Running in main thread.");
        Thread.Sleep(500);
     }
     
     Console.Read();
}

如果要往线程里传递参数,Task构造函数提供的重载,可以传入一个object类型的参数:
Task task = new Task(TaskMethodWithParameter, "Hello world");
task.Start();

下面是带参的线程方法:
static void TaskMethodWithParameter(object param)
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(String.Format("Running in a task. Parameter: {0}", param));
        Thread.Sleep(500);
    }
}

2、TaskFactory类
使用实例化的TaskFactory类,在其中把TaskMethod方法传递给StartNew()方法,就会立即启动任务。
TaskFactory tf = new TaskFactory();
tf.StartNew(TaskMethod);

3、Task.Factory属性
Task类提供了一个Factory静态属性,这个属性返回一个TaskFactory对象。
Task task = Task.Factory.StartNew(TaskMethod);


///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——连续任务

通过任务,可以指定在任务完成后,应开始运行另一个特定任务。任务处理程序或者不带参数或者带一个对象参数,而连续处理程序有一个Task类型的参数。下面先定义两个任务:

static void FirstTaskMethod()
{
    Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
    Thread.Sleep(200);
}
 
static void SecondTaskMethod(Task task)
{
    Console.WriteLine("Last task is finished");
    Console.WriteLine(String.Format("Task {0} is doing something", Task.CurrentId));
    Thread.Sleep(200);
}

连续任务通过在任务上调用ContinueWith()方法来现实:
static void Main(string[] args)
{
    Task task1 = new Task(FirstTaskMethod);
    Task task2 = task1.ContinueWith(SecondTaskMethod);
    task1.Start();
 
    for (int i = 0; i < 20; i++)
    {
        Console.WriteLine("Main thread is running");
        Thread.Sleep(200);
    }
 
    Console.Read();
}
主线程循环输出字符串到控制台,Task1任务在另外一个线程里运行,FirstTaskMethod执行完继续SecondTaskMethod
值得注意的是,在一个任务结束时,可以启动多个任务,也就是说,任务的连接可以像一个树结构那样,如下代码:

Task task1 = new Task(FirstTaskMethod);
Task task2 = task1.ContinueWith(SecondTaskMethod);
Task task3 = task1.ContinueWith(SecondTaskMethod);
Task task4 = task2.ContinueWith(SecondTaskMethod);
Task task5 = task2.ContinueWith(SecondTaskMethod);
无论前一个任务是如何结束的,后面的连续任务总是在前一个任务结束时启动。
TaskContinuationOptions枚举提供了OnlyOnFaulted,NotOnFaulted,OnlyOnCanceled,
NotOnCanceled,OnlyOnRunToCompletion几个选项。我们可以指定只有当前一个任务成功结束时才启动:

Task task5 = task2.ContinueWith(SecondTaskMethod, TaskContinuationOptions.OnlyOnRanToCompletion);


///////////////////////////////////////////////////////////////////////////////////
C#异步编程的实现方式——层次任务

任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个层次结构。
下面的代码段在父任务内部新建一个任务。创建子任务的代码与创建父任务的代码相同,
唯一的区别是这个任务从另一个任务内部创建:

static void Main(string[] args)
{
    Task parentTask = new Task(ParentTask);
    parentTask.Start();
 
    Console.Read();
}
 
static void ParentTask()
{
    Console.WriteLine("Parent task is starting");
	Task childTask= new Task(ChildTask,TaskCreationOptions.AttachedToParent);
    childTask.Start();
    Thread.Sleep(2000);
    Console.WriteLine("Parent task is finished");
}
 
static void ChildTask()
{
    Console.WriteLine("Child task started");
    Thread.Sleep(4000);
    Console.WriteLine("Child task is finished");
}


///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Ex.RulesTester.Threads
{
    /// <summary>
    /// Task异步等待所有线程结束通知测试
    /// </summary>
    [TestClass]
    public class TaskAllCompleteTester
    {
        [TestMethod]
        public void TestTaskPoolStatus()
        {
            //运行异步多任务
            TaskTest.RunTask();
            var list = TaskTest.SuccessList;
            bool isAllComplete = false;
            //等待异步通知
            while (!isAllComplete)
            {
                isAllComplete = TaskTest.IsAllComplete;
                list = TaskTest.SuccessList;
            }

            Assert.IsTrue(true);
        }
        /// <summary>
        /// 对于 task 多任务执行的封装
        /// </summary>
        private class TaskTest
        {
            private static object m_lock = new object();
            public static List<string> SuccessList = new List<string>();
            private static string msg = "";
            public static bool IsFinish = false;
            public static List<Task> TaskList = new List<Task>();
            static bool isAllComplete = false;
            /// <summary>
            /// 标记所有任务是否全部执行完毕
            /// </summary>
            public static bool IsAllComplete
            {
                get { return isAllComplete; }
            }

            private TaskTest()
            {

            }

            public static void RunTask()
            {
                //运行5个任务
                for (int i = 1; i <= 5; i++)
                {
                    var task = Task.Factory.StartNew(DoTask, i);
                    TaskList.Add(task);
                }
                //异步等待所有任务执行完毕
                Task.Factory.StartNew(x =>
                {
                    Task.WaitAll(TaskList.ToArray());
                    //标记所有任务运行完成
                    isAllComplete = true;
                }, null);
            }
            private static void DoTask(object par)
            {
                Thread.Sleep(int.Parse(par.ToString()) * 1000);
                lock (m_lock)
                {
                    SuccessList.Add("Has Completed T" + par.ToString());
                }
            }

        }
    }
}

本文转载自:http://blog.csdn.net/smartsmile2012/article/details/52497114

共有 人打赏支持
深圳大道
粉丝 3
博文 877
码字总数 0
作品 0
深圳
架构师
私信 提问
C# WinForm开发系列 - Thread/Delegate/Event

C#是一门支持多线程的语言,因此线程的使用也是比较常见的。由于线程的知识在Win32编程的时候已经说得过多,所以在.Net中很少介绍这部分(可能.Net不觉得这部分是它所特有的)。那我们为什么...

长征2号
2017/10/11
0
0
C#多线程编程系列(一)- 简介

目录 一、前言 二、目录结构 四、章节结构 五、相关链接 一、前言 在C#学习过程中,多线程一直都是比较难的部分,因为其中涉及到很多与操作系统相关的知识。比如:如何进行多线程编程、线程同...

InCerry
2018/07/31
0
0
异步、多线程、任务、并行编程之一:选择合适的多线程模型

异步、多线程、任务、并行编程之一:选择合适的多线程模型 本篇概述: @FCL4.0中已经存在的线程模型,以及它们之间异同点; @多线程编程模型的选择。 1:异步、多线程、任务、并行的本质 这四...

luminji
2012/07/18
0
0
C#多线程编程系列(四)- 使用线程池

目录 1.1 简介 1.2 在线程池中调用委托 1.3 向线程池中放入异步操作 1.4 线程池与并行度 1.5 实现一个取消选项 1.6 在线程池中使用等待事件处理器及超时 1.7 使用计时器 1.8 使用BackgroundW...

InCerry
2018/08/06
0
0
C#多线程学习(四) 多线程的自动管理(线程池)

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线...

Yamazaki
2012/03/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何有效的背单词

转眼间到了大三快要结束了。英语四级考了三次了,每次都220多分。成绩很稳定,但离四级线还有200多分。学校规定如果过不了四级线,就拿不到学士学位证。没有学位证就找不到好工作,找不到好工...

我是菜鸟我骄傲
33分钟前
1
0
导出表格

https://blog.csdn.net/hhzzcc_/article/details/80419396

Js_Mei
56分钟前
0
0
Ubuntu中安装Elasticsearch

1.安装jre elasticsearch是使用java开发的搜索引擎,因此其运行依赖于java runtime environment,我们在这里不使用Oracel的官方jre,改为使用open-jre。 运行环境: ubuntu:18.04 jre:openj...

cloes
今天
0
0
nginx rails 详细站点配置入门教程

Ruby on Rails 是一个用于开发数据库驱动的网络应用程序的完整框架。Rails基于MVC(模型- 视图- 控制器)设计模式。从视图中的Ajax应用,到控制器中的访问请求和反馈,到封装数据库的模型,R...

xiangyunyan
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部