• 首页
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案
目录

C#中有哪些办法用多线程,能将文件内的元素按指定顺序输出

C#中用多线程的方法有:1、Thread类;2、线程池;3、parallel类;4、task类;5、background类。其中,使用Thread类通过ThreadStart(无参数)或ParameterizedThreadStart(一个输入参数)类型的委托创建一个Thread对象,开启一个新线程,执行该委托传递的任务。

一、C#中用多线程的方法

1、Thread类

使用Thread类通过ThreadStart(无参数)或ParameterizedThreadStart(一个输入参数)类型的委托创建一个Thread对象,开启一个新线程,执行该委托传递的任务,此时线程尚未处于运行状态。

调用Start()函数启动线程,当前线程继续执行。

调用Join()函数可以阻塞当前线程,直到调用Join()的线程终止。

调用Abort()方法,如需中止线程,在调用该方法的线程上抛出ThreadAbortException异常,以结束该线程

可以通过Thread.ResetAbort()方法阻止线程的中止。

2、线程池

ThreadPool类维护一个线程的列表,提供给用户以执行不同的小任务,减少频繁创建线程的开销。

该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。

线程池其实就是一个存放线程对象的“池子(pool)”,他提供了一些基本方法,如:设置pool中最小/最大线程数量、把要执行的方法排入队列等等。ThreadPool是一个静态类,因此可以直接使用,不用创建对象。

3、parallel类

Parallel.For()方法类似于 C#的 for循环语旬,也是多次执行一个任务。

使用Parallel.For()方法,可以并行运行迭代。

迭代的顺序没有定义,不能保证。

在For()方法中:

前两个参数定义了循环的开头和结束。示例从0迭代到 9。

第 3个参数是一个Action委托

是要并行运行迭代的方法

整数参数是循环的迭代次数,该参数被传递给Action委托引用的方法。

Parallel.For()方法的返回类型是ParalleLoopResult结构,它提供了循环是否结束的信息。

4、task类

相比于Thread类,Task类为控制线程提供了更大的灵活性。

  • Task类可以获取线程的返回值
  • 可以定义连续的任务:在一个任务结束结束后开启下一个任务
  • 可以在层次结构中安排任务,在父任务中可以创建子任务
    这样就创建了一种依赖关系,如果父任务被取消,子任务也随之取消

5、background类

C#提供了BackgroundWorker控件帮助用户更简单、安全地实现多线程运算。

该控件提供了DoWork, ProgressChanged 和 RunWorkerCompleted事件

为DoWork添加事件处理函数,再调用RunWorkerAsync()方法,即可创建一个新的线程执行DoWork任务

ProgressChanged和RunWorkerCompleted事件均在UI线程中执行,添加相应的处理函数,即可完成任务线程与UI线程间的交互,可用于显示任务的执行状态(完成百分比)、执行结果等。

同时,该控件还提供了CancleAsync()方法,以中断线程的执行

需注意的是,调用该方法后,只是将控件的CancellationPending属性置True,用户需在程序执行过程中查询该属性以判定是否应中断线程。

具体用法可参考MSDN:BackgroundWorker用法范例

可以看的出来,BackgroundWorker组件提供了一种执行异步操作(后台线程)的同时,并且还能妥妥的显示操作进度的解决方案。

延伸阅读:

二、任务Task和线程Thread的区别

任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。

任务跟线程不是一对一的关系。比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。

Task和Thread一样,位于System.Threading命名空间下。

相关文章