多线程调用有参数的方法---c# Thread 与 Task

摘要:
Task类的构造函数在创建任务时提供了更大的灵活性。下面定义了无参数方法。第二个方法使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。然后调用Task类的Start()方法来启动任务。PreferFairness的值表示调度程序应该提取已等待的第一个任务。任务处理程序没有参数或对象参数,而连续处理程序有task类型参数。在这里,您可以访问有关启动任务的信息:staticvoidDoOnFirst(){Console.WriteLine;Thread.Sleep;}staticvoidDoOnSecond{Console.WriteLine;Console.WriteLine;Console.WriteLine;Thread.Sleep;}通过对任务调用ContinueWith()方法来定义连续任务。
  C#实现多线程的方式:Task——任务  
 
 

简介

  .NET 4包含新名称空间System.Threading.Tasks,它 包含的类抽象出了线程功能。 在后台使用ThreadPool。 任务表示应完成的某个单元的工作。 这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调线程。 使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。 
  在安排需要完成的工作时,任务提供了非常大的灵活性。 例如,可 以定义连续的工 作—— 在一个任务完成后该执行什么工作。 这可以区分任务成功与否。 另外,还可以在层次结构中安排任务。例如,父任务可以创建新的子任务。 这可以创建一种依赖关系,这样,取消父任务,也会取消其子任务。

启动任务

  要启动任务,可 以使用 TaskFactory类 或 Task类 的构造函数和 Start()方法。Task类的构造函数在创建任务上提供的灵活性较大。 
  在启动任务时,会创建Task类 的一个实例,利用Action或Action<object>委托不带参数或带一个object参数 ,可以指定应运行的代码,这类似于Thread类 。下面定义了一个无参数的方法。 在实现代码中,把任务的ID写入控制台中: 

static void TaskMethod()
{
    Console.WriteLine("running in a task");
    Console.WriteLine("Task id: {0}",Task.CurrentId);
}

  在上面的代码中,可 以看到启动新任务的不同方式。第一种方式 使用实例化TaskFactory类 ,在其中把 TaskMedlod()方 法传递给StartNew()方法,就会立即启动任务。 第二种方式使用 Task类的构造函数。 实例化 Task对象时,任务不会立即运行,而是指定 Created状态。接着调用 Task类的Start()方法,来启动任务。 使用Task类 时,除了调用 Start()方法,还可以调用RunSynchronously()方法。这样,任务也会启动,但在调用者的当前线程中它正在运行,调用者需要一直等待到该任务结束。 默认情况下,任务是异步运行的。 

复制代码
//using task factory
    TaskFactory tf = new TaskFactory();
    Task t1 = tf.StartNew(TaskMethod);

//using the task factory via a task
    Task t2 = Task.TaskFactory.StartNew(TaskMethod);

//using Task constructor
    Task t3 = new Task(TaskMethod);
    t3.Start();
复制代码

  使用Task类的构造函数和TaskFactory类的StartNew()方法时,都可以传递TaskCreationOptions枚举中的值。设置LongRunning选项,可以通知任务调度器,该任务需要较长时间执行,这样调度器更可能使用新线程。如果该任务应关联到父任务上,而父任务取消了,则该任务也应取消,此时应设置 AuachToParent选项。PreferFairness的值表示,调度器应提取出已在等待的第一个任务。 如果一个任务在另一个任务内部创建,这就不是默认情况 。如果任务使用子任务创建了其他工作,子任务就优先于其他任务。 它们不会排在线程池队列中的最后。 如果这些任务应以公平的方式与所有其他任务一起处理,就设置该选项为PreferFairness。 
  

Task t4 = new Task(TaskMethod, TaskCreationOptions.PreferFairness);
t4.Start();

连续任务

   通过任务,可 以指定在任务完成后,应开始运行另一个特定任务,例如,一个使用前一个任务的结果的新任务,如 果前一个任务失败了,这个任务就应执行一些清理工作。 
  任务处理程序或者不带参数或者带一个对象参数,而连续处理程序有一个 Task类 型的参数,这里可以访问起始任务的相关信息: 
  

复制代码
static void DoOnFirst()
{
    Console.WriteLine("doing some task {0}",Task.CurrentId);
    Thread.Sleep(3000);
}

static void DoOnSecond(Task t)
{
    Console.WriteLine("task {0} finished", t.Id);
    Console.WriteLine("this task id {0}", Task.CurrentId);
    Console.WriteLine("do some cleanup");
    Thread.Sleep(3000);
}
复制代码

   连续任务通过在任务上调用ContinueWith()方法来定义。也可以使用TaskFactory类来定义。t1.ContinueWith(DoOnSecond)方 法表示,调用DoOnSecond()方法的新任务应在任务t1结束时立即启动。在一个任务结束时,可以启动多个任务,连续任务也可以有另一个连续任务,如下面的例子所示:

Task t1 = new Task(DoOnFirst);
Task t2 = t1.ContinueWith(DoOnSecond);
Task t3 = t1.ContinueWith(DoOnSecond);
Task t4 = t2.ContinueWith(DoOnSecond);

   无论前一个任务是如何结束的,前 面的连续任务总是在前一个任务结束时启动。 使用TaskContinuationOptions枚举中的值,可以指定,连续任务只有在起始任务(或失败)结束时启动。一些可能的值是OnlyOnFaulted、 NotOnFaulted、 OnlyOnCanceled、 NotOnCanceled和OnlyOnRanToCompletion。 

Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);

任务层次结构

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

  • 复制代码
    static void ParentAndChild()
    {
        var parent = new Task(ParentTask);
        parent.Start();
        Thread.Sleep(2000);
        Console.WriteLine(parent.Status);
        Thread.Sleep(4000);
        Console.WriteLine(parent.Status);
    }
    
    static void ParentTask()
    {
        Console.WriteLine("task id {0}", Task.CurrentId);
        var child = new Task(ChildTask);
        child.Start();
        Thread.Sleep(1000);
        Console.WriteLine("parent started child");
    }
    
    static void ChildTask()
    {
        Console.WriteLine("child");
        Thread.Sleep(5000);
        Console.WriteLine("child finished");
    }
    复制代码

  如果父任务在子任务之前结束,父任务的状态就显示为WaitingForChildrenToComplete。 只要子任务也结束时,父任务的状态就变成RanToCompletion。 当然,如 果父任务用TaskCreationOptions枚举中的 DetachedFromParent创建子任务时,这就无效。

任务的结果

  任务结束时,它可以把一些有用的状态信息写到共享对象中。这个共享对象必须是线程安全的。另一个选项是使用返回某个结果的任务。使用 Task类 的泛型版本,就可以定义返回某个结果的任务的返回类型。 
  为了返回某个结果任务调用的方法可以声明为带任意返回类型。示例方法TaskWithResult()利用一个元组返回两个int值。 该方法的输入可以是void或object类型,如下所示: 

复制代码
static Tuple<int, int> TaskWithResult(object division)
{
    Tuple<int, int> div =(Tuple<int, int>)division;
    int result = div.Item1/div.Item2;
    int reminder = div.Item1%div.Item2;
    Console.WriteLine("task creates a result...");

    return Tuple.Create<int, int>(result, reminder);
}
复制代码

  定义一个调用 StartWithResult()方法的任务时,要使用泛型类Task<Tresult>。 泛型参数定义了返回类型。通过构造函数,把这个方法传递给Func委 托,第二个参数定义了输入值。 因为这个任务在object参数中需要两个输入值,所以还创建了一个元组。 接着启动该任务。 Task实例t1的Result属性被禁用,并一直等到该任务完成。任务完成后,Result属性包含任务的结果。 
 

var t1 = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));
t1.Start();
Console.WriteLine(t1.Result);
t1.Wait();
Console.WriteLine("result from task: {0} {1}",t1.Result.Item1, t1.Result.Item2);

  备注:上例中,Task<Tresult>构造函数调用了TaskFactory.StartNew 方法的 (Func<Object, TResult>, Object)重载。 
  function 
    类型:System.Func<Object, TResult> 
    一个函数委托,可返回能够通过任务获得的将来结果。

  state 
    类型:System.Object 
    包含 function 委托所用数据的对象。

  因此我们可以知道,为什么在实例化t1的时候,为什么要创建一个新的Tuple对象了。

转载来源:http://blog.csdn.net/honantic/article/details/46790707

c#多线程调用有参数的方法

Thread (ParameterizedThreadStart) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。   
Thread (ThreadStart) 初始化 Thread 类的新实例。  
由 .NET Compact Framework 支持。  
Thread (ParameterizedThreadStart, Int32) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈大小。   
Thread (ThreadStart, Int32) 初始化 Thread 类的新实例,指定线程的最大堆栈大小。  
由 .NET Compact Framework 支持。  
  我们如果定义不带参数的线程,可以用ThreadStart,带一个参数的用ParameterizedThreadStart。带多个参数的用另外的方法,下面逐一讲述。  

 

一、不带参数的 

 
复制代码
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Threading;  
 
namespace AAAAAA  
{  
  class AAA  
  {  
  public static void Main()  
  {  
  Thread t = new Thread(new ThreadStart(A));  
  t.Start();  
 
  Console.Read();  
  }  
 
  private static void A()  
  {  
  Console.WriteLine("Method A!");  
  }  
  }  
}
复制代码
 

结果显示Method A! 

 

二、带一个参数的  

 
复制代码
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Threading;  
 
namespace AAAAAA  
{  
  class AAA  
  {  
  public static void Main()  
  {   
  Thread t = new Thread(new ParameterizedThreadStart(B));  
  t.Start("B");  
 
  Console.Read();  
  }  
 
  private static void B(object obj)  
  {  
  Console.WriteLine("Method {0}!",obj.ToString ());  
 
  }  
  }  
}
复制代码
 

结果显示Method B! 

   

三、带多个参数的  
  由于Thread默认只提供了这两种构造函数,如果需要传递多个参数,我们可以自己将参数作为类的属性。定义类的对象时候实例化这个属性,然后进行操作。 

   
复制代码
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Threading;  
 
namespace AAAAAA  
{  
  class AAA  
  {  
  public static void Main()  
  {  
  My m = new My();  
  m.x = 2;  
  m.y = 3;  
 
  Thread t = new Thread(new ThreadStart(m.C));  
  t.Start();  
 
  Console.Read();  
  }  
  }  
 
  class My  
  {  
  public int x, y;  
 
  public void C()  
  {  
  Console.WriteLine("x={0},y={1}", this.x, this.y);  
  }  
  }  
}
复制代码
 

结果显示x=2,y=3 

   

四、利用结构体给参数传值。  
定义公用的public struct,里面可以定义自己需要的参数,然后在需要添加线程的时候,可以定义结构体的实例。

   
复制代码
//结构体  
  struct RowCol  
  {  
  public int row;  
  public int col;  
  };  
 
//定义方法  
public void Output(Object rc)  
  {  
  RowCol rowCol = (RowCol)rc;  
  for (int i = 0; i < rowCol.row; i++)  
  {  
  for (int j = 0; j < rowCol.col; j++)  
  Console.Write("{0} ", _char);  
  Console.Write("
");  
  }  
  }
复制代码
 

来自http://www.cnblogs.com/warioland/archive/2011/10/13/2210545.html

免责声明:文章转载自《多线程调用有参数的方法---c# Thread 与 Task》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇《网络协议分析及编程》 复习搜整vue 2.0 及 vue 3.0 rem配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python——多线程与线程锁

一、概念: 进程:对系统过来说,一个任务是一个进程; 线程:线程是包含在进程中。进程中,线程来工作,线程是最小的单位。一个进程可以启多个线程 二、进程和线程使用时的选择: 1.cpu密集型任务,用进程 #比如排序、计算的功能2.IO密集型任务,多线程 input Output #读写频繁,网络IO或者磁盘IO。浪费CPU比较少的用多线程3.如果需要读写也需...

zz《C++并发编程实战》的读书笔记

multi_threading 《C++并发编程实战》的读书笔记,供以后工作中查阅。 第一章 何谓并发和多线程 并发:单个系统里同时执行多个独立的活动。 多线程:每个线程相互独立运行,且每个线程可以运行不同的指令序列。但进程中所有线程都共享相同的地址空间,并且从所有的线程中访问到大部分数据。 为什么要在应用程序中使用并发和多线程 关注点分离(DVD程序逻辑...

android Launcher——启动过程详解

一LauncherApplication->onCreate        --1.//设置最小堆内存4M        --2.//建立应用图标缓存器        --3.//建立LauncherModel        --4.//注册Intent.ACTION_PACKAGE_ADDED,Intent.ACTION_PACKAGE_REMOV...

Spring c3p0连接池无法释放解决方案

通过c3p0配置连接池的时候,在进行压力测试的时候,日志出现了这样一个错误:Data source rejected establishment of connection, message from server: “Too many connections” 数据库的连接过多。 然后查看mysql的最大连接数,为100。 于是便更改最大连接池。 由于...

性能测试三十二:监控之Java线程监控

线程的五种状态* 新建:new* 运行:runnable* 等待:waitting(无限期等待),timed waitting(限期等待)* 阻塞:blocked* 结束:terminated 线程的两种监控方法一,jvisualvm,图形界面的方式监控之前先对jvm加监控参数,在tomcat的bin目录下,catalina.sh文件中,第二行添加:JA...

这几个IDEA高级调试技巧,用完就是香

一个项目启动两次 测试分布式项目时,经常要一个项目启动2次,不用将一个项目打开多次启动,配置一下即可 1.点击Edit Configurations 2.勾选Allow parallel run 3.依次点击如下2个按钮 条件断点 有如下代码,只想让它在i == 10的情况下停下来 @Test public void condition() {...