【多线程】Task

介绍

Task是.NET推出数据任务处理的工作类。位于System.Threading.Tasks命名空间下,通过命名空间也可以看出是个多线程类。

创建Task:

Task有很多构造函数,无参有参都有,想了解更多可以去官网查看。这里只介绍经常用的形式。

第一种:以类的实例化形式进行创建Task。通过实例化一个Task对象,然后Start,这种方式中规中矩。

 Task Task1 = new Task(() => Console.WriteLine("Task"));
Task1.Start();

第二种:在实践中通常使用这种简洁形式,这种直接运行了Task不需要在start调用

Task.Run(() => Console.WriteLine("Task"));

第三种:通过Task的静态属性创建,然后直接启动。Factory提供对用于创建 Task 和 Task<TResult> 的工厂方法的访问。

     var t1= Task.Factory.StartNew(() =>
{
Console.WriteLine("Task");
});

StartNew和Run区别

这两个应用的场景都是一样的,只不过Run是StartNew的再次封装吧,与之相比Run比StartNew自动执行了Unwrap。

Unwrap:主要的作用就是会把嵌套在Task或者Task<>的结果提取出来。

判断执行状态:

通过IsCompleted属性可以查看当前task是否执行完成。

       var t11 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task");
});
if (t11.IsCompleted)
{
Console.WriteLine("线程已经完成");
}

等待控制:

通过WhenAny和WhenAll来控制等待,WhenAny表示任意一个Task完成之后,返回这个Task对象,但是有时候我们需要等待任务的完成,WhenAll表示处理完成之后,返回所有对象实例。例如:

List<Task<string>> TaskList = new List<Task<string>>() {
Task.Factory.StartNew(()=> { return WriteHello(); },C1.Token),
Task.Factory.StartNew(()=> { return WriteHello(); },C1.Token),
Task.Factory.StartNew(()=> { return WriteHello(); },C1.Token),
Task.Factory.StartNew(()=> { return WriteHello(); },C1.Token)
};
//var Reuslt= await Task.WhenAll(TaskList);
var Reuslt = await Task.WhenAny(TaskList);
if (Reuslt.IsCompleted)
{
Console.WriteLine("有人完成了");
}

等待的时候,要加上async 和 await;

以上是异步等待,要想实现同步操作使用AwaitAll

         var t1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task1");
});
var t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task2");
});
var t3 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task3");
}); //等待并行完成
Task.WaitAll(t1, t2, t2, t3);

此时只有执行完成所有task后才会执行下面的代码。

死锁问题

此代码仅作保存研究

出现死锁:

  #region 并行死锁问题
public static void ParallelLock()
{
var t1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task 1 Start running...");
while (true)
{
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Task 1 Finished!");
});
var t2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task 2 Start running...");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 2 Finished!");
});
Task.WaitAll(t1, t2);
}
#endregion

解决办法:

  #region 解决死锁问题
/// <summary>
/// 解决死锁问题设置时间
/// </summary>
public static void ParallelLockEnd()
{
Task[] tasks = new Task[];
tasks[] = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task 1 Start running...");
while (true)
{
System.Threading.Thread.Sleep();
}
Console.WriteLine("Task 1 Finished!");
});
tasks[] = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task 2 Start running...");
System.Threading.Thread.Sleep();
Console.WriteLine("Task 2 Finished!");
}); Task.WaitAll(tasks, );
for (int i = ; i < tasks.Length; i++)
{
if (tasks[i].Status != TaskStatus.RanToCompletion)
{
Console.WriteLine("Task {0} Error!", i + );
}
}
Console.Read();
}
#endregion
上一篇:C#多线程编程のTask(任务全面解析)


下一篇:文件IO模型