多线程调用有参数的方法---c# Thread 与 Task
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("\n");
}
}

来自http://www.cnblogs.com/warioland/archive/2011/10/13/2210545.html
多线程调用有参数的方法---c# Thread 与 Task的更多相关文章
- c#多线程调用有参数的方法
Thread (ParameterizedThreadStart) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托. Thread (ThreadStart) 初始 ...
- C#线程调用带参数的方法
在 .NET Framework 2.0 版中,要实现线程调用带参数的方法有两种办法.第一种:使用ParameterizedThreadStart.调用 System.Threading.Thread ...
- MVC 5 调用存储过程参数配置方法-Procedure or function 'UP_***' expects parameter '@****', which was not supplied.
MVC 5 调用存储过程参数配置方法-Procedure or function 'UP_***' expects parameter '@****', which was not supplied. ...
- Javascript 定时器调用传递参数的方法
文章来源: https://m.jb51.net/article/20880.htm 备注:先记下,以后整理: Javascript 定时器调用传递参数的方法,需要的朋友可以参考下. 无论是wind ...
- java通过反射调用有参数的方法
public static void eachCfg(Class Initclass,String taskType){ Field[] fields = Initclass.getDeclaredF ...
- c# 多线程 调用带参数函数
线程操作主要用到Thread类,他是定义在System.Threading.dll下.使用时需要添加这一个引用.该类提供给我们四个重载的构造函数(以下引自msdn). Thread (Pa ...
- java通过反射调用不同参数的方法
import java.lang.reflect.Method; public class testReflect { /** * @param args */ public static void ...
- C#线程调用带参数的方法,给控件赋值
System.Threading.Thread thread = new System.Threading.Thread(() => { //各种业务 //定义一个委托 public deleg ...
- .NET多线程(Thread,ThreadPool,Task,Async与Await)
.NET多线程是什么? 进程与线程 进程是一种正在执行的程序. 线程是程序中的一个执行流. 多线程是指一个程序中可以同时运行多个不同的线程来执行不同的任务. .NET中的线程 Thread是创建和控制 ...
随机推荐
- dubbo-本地直连
一.背景 目前项目是基于dubbo做为rpc,zk为注册中心实现多个微服务之间的远程服务调用.但需要本地联调dubbo接口时,需要绕过注册中心,达到不干扰线上服务,即只订阅不注册服务的目的. 二.实现 ...
- 【概率论】5-3:超几何分布(The Hypergeomtric Distribution)
title: [概率论]5-3:超几何分布(The Hypergeomtric Distribution) categories: - Mathematic - Probability keyword ...
- 第四组团队git现场编程实战
组员职责分工 组员 分工 林涛(组长) 分配任务.整理数据.写博客 童圣滔 UI界面制作 林红莲 UI界面制作 潘雨佳 测评出福州最受欢迎的商圈 于瀚翔 测评出福州最受欢迎的商圈 覃鸿浩 测评出福州人 ...
- webkit vs v8
我们知道不同浏览器用的不同的渲染引擎: Tridend(IE).Gecko(FF).WebKit(Safari,Chrome,Andriod浏览器) 当然 Chrome 重构了一下 WebKit 然后 ...
- SDK评测
这个作业属于哪个课程 这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/2019FZUSEZ/homework/10081 这个作业的目标 每个人发表一篇随笔, ...
- JVM 堆内存溢出后,其他线程是否可继续工作
最近网上出现一个美团面试题:“一个线程OOM后,其他线程还能运行吗?”.我看网上出现了很多不靠谱的答案.这道题其实很有难度,涉及的知识点有jvm内存分配.作用域.gc等,不是简单的是与否的问题. 由于 ...
- git 删除目录及子目录下的同名文件
find . -name ".git" | xargs rm -Rf find . -name ".gitignore" | xargs rm -Rf
- FM与FFM深入解析
因子机的定义 机器学习中的建模问题可以归纳为从数据中学习一个函数,它将实值的特征向量映射到一个特定的集合中.例如,对于回归问题,集合 T 就是实数集 R,对于二分类问题,这个集合可以是{+1,-1}. ...
- 雪花算法(DELPHI实现)
雪花算法(DELPHI实现) 生成ID能够按照时间有序生成. 分布式系统内不会产生重复id(用workerId来做区分). 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景. GUID:采用无 ...
- Go --- 七牛云 上传文件 & Token demo
package main import ( "bytes" "crypto/hmac" "crypto/sha1" "encodi ...