在CSDN上没人能解决问题,只好请大富翁上的高手出招了!(关于多任务线程)(5分)

  • 主题发起人 主题发起人 fullstrong
  • 开始时间 开始时间
F

fullstrong

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一个任务列表,其中有23个任务,我想我每次开四个线程执行四个任务,当四个中
的任务有一个完成后,自动新增一个线程来完成另一个任务,每次保持有四个线程在执行
任务,直到全部的任务完成(就好象FlashGet的多任务下载一样),
一。 我想知道如何开线程象上面讲的那样来完成全部任务?
二。 如何当完成四个任务后,再执行四个任务,线程之间的接口如何做?
答者有分,不够再加!
 
你不必新增线程,只需要在一个任务完成时,将线程RESET,顺序提取下一个任务就行。
像是一个任务排队处理机,也就没有什么线程之间的接口了。新增线程既浪费资源又难
以衔接,不是好办法。
 
如果任务完成,没有新任务时,可以让线程等待或暂时挂起。
 

有道理,不知如果要想象我的要求那样,又该如何做呢?
 
你要钻牛角尖呀。那你就写一个检查任务并决定是否启动线程的过程,在线程结束时调用
它就行了:
TMyThread = class(TThread)
public
procedure CheckTask;
end;

procedure CheckTaskAndStartThread;
begin
if 有任务在排队 then
TMyThread.Create(...);
end;

procedure TMyThread.CheckTask;
begin
CheckTaskAndStartThread;
end;

procedure TMyThread.Execute;
begin
... //执行任务
Synchronize(CheckTask);
//结束前检查任务
end;

另外:你的分太少了,我有意见。
 
to Huzzz:
分是少了一点,但我想意义不在于分, :-)
一。你上面讲的有一点疑问我想请教,在父线程中生成的子线程,当父线程结束时,会不
会影响生成的子线程。
二。如果我采取你讲的第一种方法,那么我只要生成四个线程,这四个线程就循环的提取
任务列表中的任务,并执行,直到任务列表中的任务全部被执行完毕,这样的话,总共就只
需要创建四个线程就行了,我在这里想请教的是: 这四个线程将如何知道任务列表中的任务
哪些已被执行,哪些还没有被执行,然后分别将任务列表中的没有被执行任务全部被执行完毕?
希望你能详细讲一下算法? 谢了!
 
设一个当前任务指针,每个线程提取任务的时候提取该指针指向的任务,然后将任务指针加一,
获取任务并将指针加一的这段得设置临界区以保证线程互斥访问该指针。
 
>>当父线程结束时,会不会影响生成的子线程。
我认为WINDOWS中并没有严格的父线程子线程之分,只是在DELPHI中有主线程和副线程
之说。主副线程之间并没有什么影响。但如果它们访问了共享资源(如一个FORM),则
需要注意(主线程结束时多半把这个FORM给FREE掉了,副线程再访问就会死掉)
>>如何知道任务列表中的任务哪些已被执行,哪些还没有被执行
你建立一个线程安全的任务LIST(可以TThreadList中继承下来),每个任务有一个状
态标记:排队等待中、正在执行中、已经执行完,就行了。
 
csdn 高手太少。
 
其实满简单,要做的就是自己管理任务队列,象楼上的兄弟说的一样,至于管理方法就看自己的需要和理解了,楼上的说的很清楚了
只是提醒一点,在设置任务队列状态时要特别注意线程的互斥问题,以免多个线程同时处理一个任务。
 
to Huzzz:
谢谢你的回答,我是刚学线程编写,不是很懂,如果你能够写一个简单的四个线程执行完一个
多任务列表的程序列子就好了。
 
行吧,我有空就写一个。
 
to Huzzz:
快点啊,麻烦你了,我很急。
 
你真可以啊。我不知道是帮你还是害你,但希望对你有帮助。下面是我写的DEMO:
两个单元:Unit1和Unit2。UNIT1主要是界面,UNIT2则是线程和任务LIST实现。
//*****************Unit1.pas********************
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, CheckLst, Unit2, ExtCtrls;
type
TForm1 = class(TForm)
CheckListBoxTasks: TCheckListBox;
Label1: TLabel;
ButtonAddRandomTask: TButton;
ButtonStopCurTask: TButton;
ButtonPauseTask: TButton;
ButtonExit: TButton;
ButtonAddTask: TButton;
EditTaskTime: TEdit;
TimerRefreshList: TTimer;
ButtonDelTask: TButton;
ButtonContinueTask: TButton;
procedure ButtonExitClick(Sender: TObject);
procedure ButtonAddTaskClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure TimerRefreshListTimer(Sender: TObject);
procedure ButtonAddRandomTaskClick(Sender: TObject);
procedure ButtonDelTaskClick(Sender: TObject);
procedure ButtonStopCurTaskClick(Sender: TObject);
procedure ButtonPauseTaskClick(Sender: TObject);
procedure ButtonContinueTaskClick(Sender: TObject);
private
{ Private declarations }
FTaskList: TTaskList;
FTaskIdx: Integer;
FThreads: array of TTaskThread;
public
{ Public declarations }
end;

var
Form1: TForm1;
const
THREAD_COUNT = 4;
implementation
{$R *.dfm}
procedure TForm1.ButtonExitClick(Sender: TObject);
begin
Close;
end;

procedure TForm1.ButtonAddTaskClick(Sender: TObject);
begin
Inc(FTaskIdx);
FTaskList.AddTask(Format('Task%d', [FTaskIdx]),
StrToIntDef(EditTaskTime.Text, 1000));
end;

procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
FTaskList := TTaskList.Create;
FTaskIdx := 0;
Randomize;
SetLength(FThreads, THREAD_COUNT);
for I := 0 to High(FThreads)do
FThreads := TTaskThread.Create(FTaskList);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
I, J: Integer;
begin
for I := 0 to High(FThreads)do
FThreads.Terminate;
for I := 0 to High(FThreads)do
while FThreads.Suspendeddo
FThreads.Resume;
for I := 0 to High(FThreads)do
begin
//等待线程退出
while WaitForSingleObject(FThreads.Handle, 0) <> WAIT_OBJECT_0do
for J := 0 to 1000do
Application.ProcessMessages;
end;

FTaskList.Free;
end;

procedure TForm1.TimerRefreshListTimer(Sender: TObject);
var
AList: TList;
Item: PTaskRecord;
I, C: Integer;
S: string;
begin
AList := FTaskList.LockList;
try
C := CheckListBoxTasks.Count;
if CheckListBoxTasks.Count < AList.Count then
for I := AList.Count - 1do
wnto CheckListBoxTasks.Countdo
begin
Item := AList.Items;
S := Format('%s %d %s %d%%', [Item.Name, Item.Time,
TTaskStatusNames[Item.Status], Round(Item.DoneTimes / Item.Time * 100)]);
CheckListBoxTasks.Items.Add(S);
end;

if CheckListBoxTasks.Count > AList.Count then
begin
C := AList.Count;
for I := CheckListBoxTasks.Count - 1do
wnto AList.Count - 1do
CheckListBoxTasks.Items.Delete(I);
end;

for I := C - 1do
wnto 0do
begin
Item := AList.Items;
S := Format('%s %d %s %d%%', [Item.Name, Item.Time,
TTaskStatusNames[Item.Status], Round(Item.DoneTimes / Item.Time * 100)]);
if CheckListBoxTasks.Items.Strings <> S then
CheckListBoxTasks.Items.Strings := S;
end;

finally
FTaskList.UnlockList;
end;

for I := 0 to High(FThreads)do
if FThreads.Suspended then
FThreads.CheckTask;
end;

procedure TForm1.ButtonAddRandomTaskClick(Sender: TObject);
begin
Inc(FTaskIdx);
FTaskList.AddTask(Format('Task%d', [FTaskIdx]),
Random(3000) + 1000);
end;

procedure TForm1.ButtonDelTaskClick(Sender: TObject);
var
ID: Integer;
begin
if CheckListBoxTasks.ItemIndex >= 0 then
begin
ID := CheckListBoxTasks.ItemIndex;
if FTaskList.Items[ID].Status <> tsRunning then
CheckListBoxTasks.DeleteSelected;
FTaskList.DelTask(ID);
if CheckListBoxTasks.Count > ID then
CheckListBoxTasks.ItemIndex := ID;
end;
end;

procedure TForm1.ButtonStopCurTaskClick(Sender: TObject);
begin
if CheckListBoxTasks.ItemIndex >= 0 then
FTaskList.TaskCommand(CheckListBoxTasks.ItemIndex, tcStop);
end;

procedure TForm1.ButtonPauseTaskClick(Sender: TObject);
begin
if CheckListBoxTasks.ItemIndex >= 0 then
FTaskList.TaskCommand(CheckListBoxTasks.ItemIndex, tcPause);
end;

procedure TForm1.ButtonContinueTaskClick(Sender: TObject);
begin
if CheckListBoxTasks.ItemIndex >= 0 then
FTaskList.TaskCommand(CheckListBoxTasks.ItemIndex, tcRun);
end;

end.

//*****************Unit1.dfm********************
object Form1: TForm1
Left = 295
Top = 107
Width = 458
Height = 311
Caption = 'TaskThread Demo'
Color = clBtnFace
Font.Charset = GB2312_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = '宋体'
Font.Style = []
OldCreateOrder = False
Position = poDefaultPosOnly
Scaled = False
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 12
object Label1: TLabel
Left = 16
Top = 16
Width = 60
Height = 12
Caption = '任务列表:'
end
object CheckListBoxTasks: TCheckListBox
Left = 16
Top = 36
Width = 185
Height = 233
ItemHeight = 12
TabOrder = 0
end
object ButtonAddRandomTask: TButton
Left = 244
Top = 64
Width = 121
Height = 25
Caption = '增加任务(随机延时)'
TabOrder = 1
OnClick = ButtonAddRandomTaskClick
end
object ButtonStopCurTask: TButton
Left = 244
Top = 104
Width = 121
Height = 25
Caption = '中止当前任务'
TabOrder = 2
OnClick = ButtonStopCurTaskClick
end
object ButtonPauseTask: TButton
Left = 244
Top = 136
Width = 121
Height = 25
Caption = '暂停任务'
TabOrder = 3
OnClick = ButtonPauseTaskClick
end
object ButtonExit: TButton
Left = 248
Top = 224
Width = 121
Height = 25
Caption = '退出'
TabOrder = 4
OnClick = ButtonExitClick
end
object ButtonAddTask: TButton
Left = 244
Top = 36
Width = 121
Height = 25
Caption = '增加任务'
TabOrder = 5
OnClick = ButtonAddTaskClick
end
object EditTaskTime: TEdit
Left = 208
Top = 40
Width = 33
Height = 20
TabOrder = 6
Text = '3000'
end
object ButtonDelTask: TButton
Left = 244
Top = 192
Width = 121
Height = 25
Caption = '删除任务'
TabOrder = 7
OnClick = ButtonDelTaskClick
end
object ButtonContinueTask: TButton
Left = 244
Top = 164
Width = 121
Height = 25
Caption = '继续任务'
TabOrder = 8
OnClick = ButtonContinueTaskClick
end
object TimerRefreshList: TTimer
Interval = 200
OnTimer = TimerRefreshListTimer
Left = 208
Top = 96
end
end
//*****************Unit2.pas********************
{
*****************************************************************
TaskThread
多线程任务处理 DEMO
(for fullstrong)
Date: 2001-12-14
By HUZZZ (huz0123@21cn.com)
Guangzhou China.
*****************************************************************
}
unit Unit2;
interface
uses
Classes, Windows;
type
//状态:未知,等待,运行,暂停,完成
TTaskStatus = (tsUnknow, tsWaiting, tsRunning, tsPause, tsFinished);
//命令:无,运行,暂停,停止
TTaskCommandd = (tcNone, tcRun, tcPause, tcStop);
TTaskRecord = record
Name: string;
Time: Integer;
Command: TTaskCommandd;
Status: TTaskStatus;
do
neTimes: Integer;
end;
PTaskRecord = ^TTaskRecord;
TTaskList = class(TThreadList)
private
function GetItems(Index: Integer): TTaskRecord;
procedure SetItems(Index: Integer;
const Value: TTaskRecord);
{ Private declarations }
protected
public
destructor Destroy;
override;
procedure AddTask(AName: string;
ATime: Integer);
procedure DelTask(Index: Integer);
procedure TaskCommand(Index: Integer;
Command: TTaskCommandd);
property Items[Index: Integer]: TTaskRecord read GetItems write SetItems;
end;

TTaskThread = class(TThread)
private
FTaskList: TTaskList;
FCurTask: PTaskRecord;
FRunTimes: Integer;
function GetTaskFinished: Boolean;
{ Private declarations }
protected
procedure Execute;
override;
public
procedure CheckTask;
constructor Create(TaskList: TTaskList);
property TaskFinished: Boolean read GetTaskFinished;
end;

const
TTaskStatusNames: array[TTaskStatus] of string =
('未知', '等待', '运行', '暂停', '完成');
implementation
{ TTaskList }
procedure TTaskList.AddTask(AName: string;
ATime: Integer);
var
AList: TList;
Item: PTaskRecord;
begin
AList := LockList;
try
Item := New(PTaskRecord);
Item.Name := AName;
Item.Time := ATime;
Item.DoneTimes := 0;
Item.Command := tcNone;
Item.Status := tsWaiting;
AList.Add(Item);
finally
UnlockList;
end;
end;

procedure TTaskList.DelTask(Index: Integer);
var
AList: TList;
Item: PTaskRecord;
begin
AList := LockList;
try
Item := AList.Items[Index];
if Item.Status = tsRunning then
begin
Item.Command := tcPause;
Exit;
end;
AList.Remove(Item);
Dispose(Item);
finally
UnlockList;
end;
end;

destructor TTaskList.Destroy;
var
AList: TList;
Item: PTaskRecord;
I: Integer;
begin
AList := LockList;
try
for I := AList.Count - 1do
wnto 0do
begin
Item := AList.Items;
//AList.Remove(Item);
Dispose(Item);
end;
finally
UnlockList;
end;
inherited;
end;

function TTaskList.GetItems(Index: Integer): TTaskRecord;
var
AList: TList;
begin
AList := LockList;
try
Result := TTaskRecord(AList.Items[Index]^);
finally
UnlockList;
end;
end;

procedure TTaskList.SetItems(Index: Integer;
const Value: TTaskRecord);
var
AList: TList;
begin
AList := LockList;
try
TTaskRecord(AList.Items[Index]^) := Value;
finally
UnlockList;
end;
end;

{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TTaskThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
procedure TTaskList.TaskCommand(Index: Integer;
Command: TTaskCommandd);
var
AList: TList;
Item: PTaskRecord;
begin
AList := LockList;
try
Item := AList.Items[Index];
Item.Command := Command;
finally
UnlockList;
end;
end;

{ TTaskThread }
procedure TTaskThread.CheckTask;
var
AList: TList;
I: Integer;
ATask: PTaskRecord;
begin
if Assigned(FCurTask) then
begin
if FRunTimes >= FCurTask.Time then
begin
FTaskList.LockList;
try
FCurTask.Status := tsFinished;
FCurTask.DoneTimes := FRunTimes;
finally
FTaskList.UnlockList;
end;
FCurTask := nil;
end
else
if FCurTask.Command = tcStop then
begin
FTaskList.LockList;
try
FCurTask.Status := tsWaiting;
finally
FTaskList.UnlockList;
end;
FCurTask := nil;
end
else
if FCurTask.Command = tcPause then
begin
FTaskList.LockList;
try
FCurTask.Status := tsPause;
finally
FTaskList.UnlockList;
end;
FCurTask := nil;
end;
end;

if not Assigned(FCurTask) then
begin
FRunTimes := 0;
AList := FTaskList.LockList;
try
for I := 0 to AList.Count - 1do
begin
ATask := AList.Items;
case ATask.Status of
tsWaiting:
begin
FCurTask := ATask;
FCurTask.Status := tsRunning;
end;
tsPause:
if ATask.Command = tcRun then
begin
FCurTask := ATask;
FRunTimes := ATask.DoneTimes;
FCurTask.Command := tcNone;
FCurTask.Status := tsRunning;
end;
end;
if Assigned(FCurTask) then
Break;
end;
finally
FTaskList.UnlockList;
end;
end;

if Assigned(FCurTask) then
while Suspendeddo
Resume;
end;

constructor TTaskThread.Create(TaskList: TTaskList);
begin
inherited Create(True);
FTaskList := TaskList;
end;

procedure TTaskThread.Execute;
begin
{ Place thread code here }
while not Terminateddo
begin
CheckTask;
while not TaskFinished and not Terminateddo
begin
Inc(FRunTimes);
FTaskList.LockList;
try
FCurTask.DoneTimes := FRunTimes;
finally
FTaskList.UnlockList;
end;

Sleep(10);
end;
Suspend;
end;
end;

function TTaskThread.GetTaskFinished: Boolean;
begin
CheckTask;
Result := not Assigned(FCurTask);
end;

end.
 
运行后请给我一个反馈意见。
 
to Huzzz:
谢谢你,希望能经常同交流,真是高手啊!程序运行良好,暂时没有问题。再次感谢!
 
这句话我爱听。不用客气。
 
这样的问题只给5分太少了。。。我开个帖子送你200分。[:D]
 
后退
顶部