C#多线程Task的用法
程序员文章站
2022-05-05 18:00:01
...
对于多线程,我们经常使用的是Thread。在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于“任务的编程模型”所冲击,因为task会比thread具有更小的性能开销,不过大家肯定会有疑惑,任务和线程到底有什么区别呢?
任务和线程的区别:
1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。
2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制
新建任务:
class Program
{
static void TaskMethod()
{
Console.WriteLine("running in a task ");
Console.WriteLine("Task id is {0}", Task.CurrentId);
}
static void Main(string[] args)
{
//第一种建立任务的方法,工厂创建
var task1 = Task.Factory.StartNew(TaskMethod);
//第二种建立任务的方法,也是工厂创建
TaskFactory taskFactory = new TaskFactory();
var task2 = taskFactory.StartNew(TaskMethod);
// 第三种创建方式,直接实例化
var task3 = new Task(TaskMethod);
task3.Start();
Console.ReadKey();
}
}
通过使用任务,可以指定某个任务完成后,应开始运行另一个任务。
等待任务Wait();WaitAll(),Task.ContinueWith
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Finish");
});
Console.WriteLine("Before start:" + task1.Status);
task1.Start();
Console.WriteLine("After start:" + task1.Status);
task1.Wait();
Console.WriteLine("After Finish:" + task1.Status);
Console.ReadKey();
}
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
Task.WaitAll(task1, task2);
Console.WriteLine("All task finished!");
Console.ReadKey();
}
就是在第一个Task完成后自动启动下一个Task,实现Task的延续,下面我们来看下它的用法,编写如下代码
static void Task2Method(Task test)
{
Console.WriteLine("running in a task{0} ",test.Id);
Console.WriteLine("Task id is {0}", Task.CurrentId);
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task {0} Finish ", test.Id);
}
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin task{0} ", Task.CurrentId);
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 1 Finish");
});
task1.Start();
Task task2 = task1.ContinueWith(Task2Method);
Console.ReadKey();
}
或者
static void Main(string[] args)
{
var SendFeedBackTask = Task.Factory.StartNew(() => { Console.WriteLine("Get some Data!"); })
.ContinueWith<bool>(s => { return true; })
.ContinueWith<string>(r =>
{
if (r.Result)
{
return "Finished";
}
else
{
return "Error";
}
});
Console.WriteLine(SendFeedBackTask.Result);
Console.Read();
}
首先输出Get some data,然后执行第二个获得返回值true,最后根据判断返回Finished或error。输出结果:
Get some Data!
Finished
其实上面的写法简化一下,可以这样写:
Task.Factory.StartNew<string>(() => {return "One";}).ContinueWith(ss => { Console.WriteLine(ss.Result);});
取消任务
如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话就return或者抛出异常
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Task id is {0}", Task.CurrentId);
for (var i = 0; i < 1000; i++)
{
Console.WriteLine("Task is running ,i is {0}", i);
System.Threading.Thread.Sleep(1000);
if (token.IsCancellationRequested)
{
Console.WriteLine("Abort mission success!");
return;
}
}
}, token);
token.Register(() =>
{
Console.WriteLine("Canceled");
});
Console.WriteLine("Press enter to cancel task...");
Console.ReadKey();
tokenSource.Cancel();
Console.ReadKey();
这里开启了一个Task,并给token注册了一个方法,输出一条信息,然后执行ReadKey开始等待用户输入,用户点击回车后,执行tokenSource.Cancel方法,取消任务.
参考: