请问有关线程的一个问题(分数一定给)(200分)

  • 主题发起人 主题发起人 yayiye
  • 开始时间 开始时间
Y

yayiye

Unregistered / Unconfirmed
GUEST, unregistred user!
我创建一个辅助线程 从全局数组MyArray中循环随机抽取一个(根据数组长度产生的产生随机下标),并显示在文本框中。当主线程按下回车键后,辅助线程suspend,把抽取的数从全局数组删除,数组长度-1 .
再按下回车键,resume 辅助线程。
可是在有些机器上运行会死机。或者有时会死机。
是不是由于主线程修改了全局数组引起的? 怎么解决?谢谢!!!
 
你說的操作應該沒問題, 估計還是代碼的細節上有問題!
 
同意 楼上的
 
还是贴出代码大家瞧瞧吧[:)]
 
没有代码很难判断是什么问题的!
 
其实是个抽奖程序
//form
object Form1: TForm1
Left = 188
Top = 168
Width = 544
Height = 375
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
KeyPreview = True
OldCreateOrder = False
OnCreate = FormCreate
OnKeyDown = FormKeyDown
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 32
Top = 32
Width = 48
Height = 13
Caption = '当前号码'
end
object Label2: TLabel
Left = 248
Top = 24
Width = 72
Height = 13
Caption = '所有选中号码'
end
object lbtotal: TLabel
Left = 40
Top = 80
Width = 28
Height = 13
Caption = 'lbtotal'
end
object Edit1: TEdit
Left = 96
Top = 24
Width = 121
Height = 21
TabStop = False
ImeName = '中文 (简体) - 微软拼音'
ReadOnly = True
TabOrder = 0
end
object Memo1: TMemo
Left = 328
Top = 16
Width = 113
Height = 321
ImeName = '中文 (简体) - 微软拼音'
ReadOnly = True
TabOrder = 1
end
end

//***********************代码**********************
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TDrawThread = class(TThread)
private
//显示随机抽出的数
procedure ShowDigtal;
protected
procedure Execute;
override;
//抽奖
procedure DrawPrize;
public
//当前的随机位置
FRandomFoot:Integer;
//要抽出的总数
FNeedDrawCount:Integer;
//已经抽出的数目
FHasDrawCount:Integer;
//按下回车键 判定号码停止滚动还是开始滚动
FStop:Boolean;
//删除全局数组刚选中的数
procedure DelOne;
constructor Create(NeedDrawCount:Integer);
end;

TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
lbtotal: TLabel;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
private
public
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
Var
MyArray:Array of Integer;
DrawThread:TDrawThread;
constructor TDrawThread.Create(NeedDrawCount: Integer);
begin
FNeedDrawCount:=NeedDrawCount;
Inherited Create(False);
end;

procedure TDrawThread.DelOne;
Var
i:Integer;
begin
for i:=FRandomFoot to High(MyArray)-1do
MyArray:=MyArray[i+1];
SetLength(myarray,Length(Myarray)-1);
end;

procedure TDrawThread.DrawPrize;
begin
While(FHasDrawCount<FNeedDrawCount)do
begin
FRandomFoot:=Random(Length(MyArray));
Synchronize(ShowDigtal);
end;
end;

procedure TDrawThread.Execute;
begin
inherited;
DrawPrize;
end;

procedure TDrawThread.ShowDigtal;
begin
form1.edit1.Text :=IntToStr(MyArray[FRandomFoot]);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
i:Integer;
begin
Randomize;
//初始化数组
SetLength(Myarray,100);//长度100
for i:=Low(MyArray) to High(MyArray)do
MyArray:=10000+i;
//创建线程
DrawThread:=TDrawThread.Create(20);//从100个数中抽取10个不重复的数
end;

procedure TForm1.FormKeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
begin
//不是按下的空白键盘 退出
if not (Key in [32]) then
Exit;
if DrawThread.FHasDrawCount=DrawThread.FNeedDrawCount then
Exit;
DrawThread.FStop:= not DrawThread.FStop;
//数字滚动停下来
if DrawThread.FStop then
begin
DrawThread.Suspend;
memo1.Lines.Add(Edit1.Text+',');
Inc(DrawThread.FHasDrawCount);
lbTotal.Caption :='已经抽出'+Inttostr(DrawThread.FHasDrawCount);
DrawThread.DelOne;
end
else
begin
//开始新的滚动显示
DrawThread.Resume;
end;
end;

end.
 
试试:在线程中判断FStop为true就等待.
 
没用,因为可能在任何时间按下空格键,因此下列假设条件完全成立:
While(FHasDrawCount<FNeedDrawCount)do
begin
FRandomFoot:=Random(Length(MyArray));
-----> 此时主进程suspend线程,线程停在这里并且FRandomFoot 正巧等于 High(MyArray);
然后主进程调用delone删除了一个, 此时FRandomFoot为非法下标
主进程调用resume 线程继续执行......
Synchronize(ShowDigtal);
// 呵呵呵呵
end;

 
多人接受答案了。
 
后退
顶部