您的位置:首页 > 其它

.Net进阶系列(13)-异步多线程(Task和Parallel)(被替换)

2017-06-23 20:00 302 查看
[b]一. Task开启多线程的三种形式[/b]

 1. 利用TaskFactory下的StartNew方法,向StartNew传递无参数的委托,或者是Action<object>委托。

2. 利用Task.Run()开启多线程,能向其中传递无参数的委托,有参数的可以使用 Task.Run(()=>{ TestThread("ypf") })这种形式。(推荐这种方式,最简洁。)

3. 先实例化Task,然后调用Start方法进行线程的开启。 Task构造函数可以无参委托或无参委托+object类型参数。 (同样道理,无参委托赋值有参函数,可以用之前的方案解决)

    public static void Test4()
{
//一. 各种委托的赋值
//1. 无参数委托(包括方法有参数,如何赋值给无参委托)
Action act1 = TestThread3;
Action act2 = () => TestThread2("测试参数1");
Action act3 = () => TestThread("测试参数1", "测试参数2");

//2. 和方法参数对应的委托
Action act4 = () => TestThread3();
Action<string> act5 = t => TestThread2(t);
Action<string, string> act6 = (m, n) => TestThread(m, n);

//3. Action<object>委托
Action<object> act7 = t => TestThread3();
Action<object> act8 = t => TestThread2(t.ToString());
//多个参数的函数要用实例类的方法解决

//4. 委托赋值时不传参数,调用的时候传递
Action act9 = TestThread3;
Action<string> act10 = TestThread2;
Action<string, string> act11 = TestThread;

//二. TaskFactory多线程的几种情况
TaskFactory taskFactory = new TaskFactory();
//1. 调用无参委托不需要传递参数
//{
//    taskFactory.StartNew(act1);
//    taskFactory.StartNew(act2);
//    taskFactory.StartNew(act3);
//}

//2. 调用和方法参数对应的委托,需要在调用的时候传递参数
//{
//    taskFactory.StartNew(act4);
//    taskFactory.StartNew(act5, "测试参数1");  //不支持(StartNew没有这种重载)
//    taskFactory.StartNew(act6, "测试参数1", "测试参数2");  //不支持(StartNew没有这种重载)
//}

//3. 调用Action<object>委托
//{
//    taskFactory.StartNew(act7,"");
//    taskFactory.StartNew(act8, "测试参数1");
//}

//4. 调用 委托赋值时不传参数,调用的时候传递
//{
//    taskFactory.StartNew(act9);
//    taskFactory.StartNew(act10, "测试参数1");  //不支持(StartNew没有这种重载)
//    taskFactory.StartNew(act11, "测试参数1", "测试参数2");  //不支持(StartNew没有这种重载)
//}

//三. 使用Task.Run() 多线程的几种情况
//1. 调用无参委托不需要传递参数
//{
//    Task.Run(act1);
//    Task.Run(act2);
//    Task.Run(act3);
//    Task.Run(act4);
//    Task.Run(act9);
//}
//除了上述五种方式,其他均不支持

//四. 利用Task实例下的Start方法开启多线程
//1.act1 act2 act3 act4 act9  调用无参委托不需要传递参数,均可以调用
//{
//    Task task = new Task(act9);
//    task.Start();
//}
//2. Action<object>委托可以使用
//act7和act8可以调用
{
Task task = new Task(act7, "");
task.Start();
}
{
Task task = new Task(act8, "测试参数1");
task.Start();
}

}


[b]二. 线程等待的两种形式[/b]

1. 利用Task下的静态方法WaitAll和WaitAny,来进行线程等待。(如果是主线程执行,则卡主主线程,如果新建一个子线程执行,则卡主了子线程)

2. 利用TaskFactory下的ContinueWhenAny和ContinueWhenAll,来进行线程等待。



[b]三. Parallel并行计算[/b]

1. 并行计算和多线程的区别:

多线程:如果要线程等待,需要单独开辟一个线程来进行线程等待,主线程在那等着。

并行计算:开启多个线程,默认就是线程等待,主线程在那等着,所以会卡主线程。

2. 并行计算的三种形式

Parallel.Invoke();

Parallel.For();

Parallel.ForEach()

    private void button6_Click(object sender, EventArgs e)
{
Stopwatch watch = new Stopwatch();
watch.Start();
Console.WriteLine("----------------- 七.并行运算Parallel  --------------------------");
Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);

//下面的测试结果发现,主线程均被卡住
//并行计算和多线程相比的区别: 多线程执行后,需要单独再开辟一个线程等待,然后主线程在执行。 而并行计算,开启多个线程后,不需要再开辟线程等待,直接是主线程完成后续操作

#region 写法一
//{
//    Parallel.Invoke(() => this.TestThread("bct1")
//                   , () => this.TestThread("bct2")
//                   , () => this.TestThread("bct3")
//                   , () => this.TestThread("bct4")
//                   , () => this.TestThread("bct5")
//    );
//}
#endregion

#region 写法二
//{
//    //前两个参数之间的差,就为并行计算线程的个数
//    Parallel.For(5, 10, t =>
//    {
//        //这里的t分别为:5,6,7,8,9 五个数
//        string name = string.Format("bct{0}", t);
//        this.TestThread(name);
//    });
//}
#endregion

#region 写法三
//{
//    //数组里的个数,就为并行计算线程的个数
//    Parallel.ForEach(new int[] { 3, 5, 44, 55, 100 }, t =>
//          {
//              //这里的t分别为:3, 5, 44, 55, 100五个数
//              string name = string.Format("bct{0}", t);
//              this.TestThread(name);
//          });
//}
#endregion

#region 写法四
{
ParallelOptions po = new ParallelOptions()
{
MaxDegreeOfParallelism = 5    //表示最大线程数为5,后面即使配置超过5,也无效
};
Parallel.For(6, 15, po, (t, state) =>
{
string name = string.Format("bct{0}", t);
this.TestThread(name);
//state.Break();   //退出单次循环(没看到实际作用)
// state.Stop();     //退出全部循环(没看到实际作用)
//return;
});
}
#endregion

watch.Stop();
Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐