并行编程提高软件处理速度
2015-10-07 11:37
337 查看
使用 TParallel 来提速你的循环,但总有些时候,你需要运行多个可以并行执行,而又并非循环的任务。
要执行此类任务,我们可以使用 System.Threading.TTask 和 System.Threading.ITask 来简化工作。
TTask提供了一个类来创建和管理ITask实例的交互,你可以通过WaitForAll或WaitForAny等待任务的执行完成。
举个例子,假设你有两个任务:A和B。如果A执行要3秒,B要5秒,那么执行这两个任务总共需要多久?
顺序执行时(不使用TTask/ITask) = 8秒
使用TTask.WaitForAll = 5秒
使用TTask.WaitForAny = 3秒
具体取决于你要做什么,返回的速度可以显著加快。下面让我们来看一段使用WaitForAll的代码例子:
procedure TFormThreading.MyButtonClick(Sender: TObject);
var
tasks: array of ITask;
value: Integer;
begin
Setlength (tasks ,2);
value := 0;
tasks[0] := TTask.Create (procedure ()
begin
sleep (3000); // 3 seconds
TInterlocked.Add (value, 3000);
end);
tasks[0].Start;
tasks[1] := TTask.Create (procedure ()
begin
sleep (5000); // 5 seconds
TInterlocked.Add (value, 5000);
end);
tasks[1].Start;
TTask.WaitForAll(tasks);
ShowMessage (*All done: * + value.ToString);
end;
上述例子中使用了一个ITask数组来处理任务集合。
返回结果Value是8000,尽管Sleep的时间共有8秒,但前3秒是并行执行的,之后2秒第二个任务也执行完毕。
也就是说,比起顺序执行两个任务,你节省了3秒钟的时间,而这一切不需要你自己创建线程和处理它们的返回。
除了加速任务执行,你还可以使用TTask来防止在长时间执行后台任务时造成的用户界面冻结,要做到这一点,你只需要创建单独的一个任务并启动它,例如:
procedure TFormThreading.Button1Click(Sender: TObject);
var
aTask: ITask;
begin
// not a thread safe snippet
aTask := TTask.Create (procedure ()
begin
sleep (3000); // 3 seconds
ShowMessage (*Hello*);
end);
aTask.Start;
end;
第二个例子,如果运行,可能会允许用户点击按钮多次,并触发多次ShowMessage调用。
虽然如此,小心使用的话,这会是运行任务的一个强大方式。
这也是一个异步编程的例子,你可以启动任务,然后继续去做其他事,等待它返回后再去处理它的结果。
ITask提供了一组方法与属性来启动、等待、取消任务,同时还有一个状态属性(Created, WaitingToRun, Running, Completed, WaitingForChildren, Canceled, Exception)
ITask作为一个接口,如果你想的话,你总是可以创建实现该接口的自定义类,以提供更高的灵活性。
要执行此类任务,我们可以使用 System.Threading.TTask 和 System.Threading.ITask 来简化工作。
TTask提供了一个类来创建和管理ITask实例的交互,你可以通过WaitForAll或WaitForAny等待任务的执行完成。
举个例子,假设你有两个任务:A和B。如果A执行要3秒,B要5秒,那么执行这两个任务总共需要多久?
顺序执行时(不使用TTask/ITask) = 8秒
使用TTask.WaitForAll = 5秒
使用TTask.WaitForAny = 3秒
具体取决于你要做什么,返回的速度可以显著加快。下面让我们来看一段使用WaitForAll的代码例子:
procedure TFormThreading.MyButtonClick(Sender: TObject);
var
tasks: array of ITask;
value: Integer;
begin
Setlength (tasks ,2);
value := 0;
tasks[0] := TTask.Create (procedure ()
begin
sleep (3000); // 3 seconds
TInterlocked.Add (value, 3000);
end);
tasks[0].Start;
tasks[1] := TTask.Create (procedure ()
begin
sleep (5000); // 5 seconds
TInterlocked.Add (value, 5000);
end);
tasks[1].Start;
TTask.WaitForAll(tasks);
ShowMessage (*All done: * + value.ToString);
end;
上述例子中使用了一个ITask数组来处理任务集合。
返回结果Value是8000,尽管Sleep的时间共有8秒,但前3秒是并行执行的,之后2秒第二个任务也执行完毕。
也就是说,比起顺序执行两个任务,你节省了3秒钟的时间,而这一切不需要你自己创建线程和处理它们的返回。
除了加速任务执行,你还可以使用TTask来防止在长时间执行后台任务时造成的用户界面冻结,要做到这一点,你只需要创建单独的一个任务并启动它,例如:
procedure TFormThreading.Button1Click(Sender: TObject);
var
aTask: ITask;
begin
// not a thread safe snippet
aTask := TTask.Create (procedure ()
begin
sleep (3000); // 3 seconds
ShowMessage (*Hello*);
end);
aTask.Start;
end;
第二个例子,如果运行,可能会允许用户点击按钮多次,并触发多次ShowMessage调用。
虽然如此,小心使用的话,这会是运行任务的一个强大方式。
这也是一个异步编程的例子,你可以启动任务,然后继续去做其他事,等待它返回后再去处理它的结果。
ITask提供了一组方法与属性来启动、等待、取消任务,同时还有一个状态属性(Created, WaitingToRun, Running, Completed, WaitingForChildren, Canceled, Exception)
ITask作为一个接口,如果你想的话,你总是可以创建实现该接口的自定义类,以提供更高的灵活性。
相关文章推荐
- java中的内存分配
- Trie树
- 全局变量、局部变量【好像java中不存在全局变量这样的概念】
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name '[beanName]'
- 黑马程序员——OC语言加强---@property中的copy关键字
- 注册表(C#)
- JAVA基础--db22_java反射机制&正则
- Java序列化(转载)
- JavaMail开发与邮件原理
- 黑马程序员——OC语言加强---copy概念及入门
- Python 全局变量的使用
- 【Python】Learn Python the hard way, ex13 传递参数
- Python 3.0 和 2.X的简单区别
- Python的ipython的安装
- c++ primer 第四章习题(2)
- Mybatis分页和Spring的集成
- ZH奶酪:PHP抓取网页方法总结
- 从零自学Hadoop(07):Eclipse插件
- 深入Java集合学习系列:深入CopyOnWriteArraySet
- 一起talk C栗子吧(第五十四回:C语言实例--图的最短路径二)