请问关于多线程 ( 积分: 100 )

  • 主题发起人 主题发起人 norlon
  • 开始时间 开始时间
N

norlon

Unregistered / Unconfirmed
GUEST, unregistred user!
用多线程来播放视频,即每播放一个视频创建一个线程。现在当我播放一个视频时没有问题,如果播放第二个视频即再创建一个线程时,则第一个线程好像是停止执行了(画面停住了)。而第二个视频正常播放。两个视频分别显示在主界面的两个已存在的panel中,线程中应该没有用到共同的数据。不知道可能是什么原因造成上面的情况,请大家帮忙,谢谢!
 
用多线程来播放视频,即每播放一个视频创建一个线程。现在当我播放一个视频时没有问题,如果播放第二个视频即再创建一个线程时,则第一个线程好像是停止执行了(画面停住了)。而第二个视频正常播放。两个视频分别显示在主界面的两个已存在的panel中,线程中应该没有用到共同的数据。不知道可能是什么原因造成上面的情况,请大家帮忙,谢谢!
 
把多线程代码贴出来,另外在访问可视化的vcl时,最好使用同步,意思就是又主线程来调动。你的线程里面使用了panel控件,这是可视化的。
 
直接使用DIRECTSHOW播放,不就得了....
 
to wlong01:因为视频文件的格式是别人指定好的,播放时用的是别人提供的库函数,所以不能用derectshow。
to cqwty:你说的同步是不是用synchronize。我用过,发现也有这样的问题,而且还使得程序响应变慢。所以就简化了一下,首先放置了两个panel,分别显示,这样应该没有什么相互影响吧,还需要同步吗?
 
感觉第一个视频虽然画面停住了,但线程依旧在运行,因为我在线程terminate后有个提示。但不知道那时是不是线程死掉了。如果判断某个线程是否还存在应该怎么办?
 
访问可视化vcl都最好使用同步控制,要不出的问题你根本就不知道为什么了。我不知道你用过e话通没有,如果你用过,那么它里面的聊天室的视频就可以多个同时播放的。你了解一下吧!
 
我想现在应该不是同步的问题了。因为现在在写panel那一部分加上用Synchronize做同步,还是有前面所说的问题。而且还使得程序响应变慢。
 
按道理应该各自一个panel是不会相互影响的了。能不能贴出你的多线程代码看看?
 
谢谢cqwty的热心帮助!
今天试着写一个简单的多线程程序。即将上面的视频变成简单的画线,来测试一下运行效果如何。
程序包括一个主界面单元和一个画线的线程。主界面有两个panel和两个paintbox,两个按钮和一个memo。主界面代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, WriteLineThread;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
PaintBox1: TPaintBox;
PaintBox2: TPaintBox;
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
var
NowPanel: integer;
//记录现在的线程数,以判断线应该画在哪个paintbox上
TempThread: TThread;

{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
NowPanel := 0;
//初始线程数为0
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if NowPanel = 2 then
exit;
//只能创建两个线程
NowPanel := NowPanel + 1;
TempThread := WriteLine.Create(NowPanel);
//创建画线线程
memo1.Lines.Add(inttostr(TempThread.ThreadID));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
TempThread.Terminate;
end;

end.

线程代码如下:
unit WriteLineThread;
interface
uses
Classes, SysUtils;
type
WriteLine = class(TThread)
private
{ Private declarations }
procedure WritePanelLine();
//画线主函数
procedure writeline();
//对vcl的操作,即在paintbox上画线
protected
procedure Execute;
override;
public
constructor Create(var NowPanel: integer);
end;

implementation
uses unit1;
var
NowPanelNumber: integer;
//记录当前线程号,即应该在哪个paintbox上画线
X,Y,H: integer;
//坐标和线长度
{ WriteLineThread }
procedure WriteLine.Execute;
begin
{ Place thread code here }
WritePanelLine;
end;

constructor WriteLine.Create(var NowPanel: integer);
begin
NowPanelNumber := NowPanel;

X := 10;
Y := 10;
H := 10;
FreeOnTerminate := true;
inherited Create(false);
end;

procedure WriteLine.WritePanelLine();
begin
while not Terminateddo
begin
synchronize(writeline);
X := X + 5;
H := H + 5;
sleep(2000);
end
end;

procedure WriteLine.writeline();
begin
if NowPanelNumber = 1 then
begin
//在paintbox1上画线
Form1.PaintBox1.Canvas.MoveTo(X,Y);
Form1.PaintBox1.Canvas.LineTo(X,Y+H);
end
else
begin
//在paintbox2上画线
Form1.PaintBox2.Canvas.MoveTo(X,Y);
Form1.PaintBox2.Canvas.LineTo(X,Y+H);
end;
end;
end.

运行程序,只有一个线程时正常。如果有两个画线线程,则paintbox1并不被绘制,paintbox2被绘制,而且速度较快(本来应该sleep(2000)),这时按下主界面上的button2,即终止掉后一个线程,发现paintbox2仍然被绘制,但速度变慢。感觉就是当有两个线程时,两个线程都在绘制paintbox2。问题可能出在NowPanelNumber的值上,但我想这是两个被分别创建的线程,线程内变量的值应该是相互独立的吧,怎么会互相影响??
 
此外,画线线程还有另一种写法,而效果又有些不同。代码如下:
unit WriteLineThread;
interface
uses
Classes, SysUtils;
type
WriteLine = class(TThread)
private
{ Private declarations }
procedure WritePanelLine();
protected
procedure Execute;
override;
public
constructor Create(var NowPanel: integer);
end;

implementation
uses unit1;
var
NowPanelNumber: integer;
X,Y,H: integer;
{ WriteLineThread }
procedure WriteLine.Execute;
begin
{ Place thread code here }
WritePanelLine;
end;

constructor WriteLine.Create(var NowPanel: integer);
begin
NowPanelNumber := NowPanel;

X := 10;
Y := 10;
H := 10;
FreeOnTerminate := true;
inherited Create(false);
end;

procedure WriteLine.WritePanelLine();
begin
if NowPanelNumber = 1 then
while not Terminateddo
begin
Form1.PaintBox1.Canvas.MoveTo(X,Y);
Form1.PaintBox1.Canvas.LineTo(X,Y+H);
X := X + 5;
H := H + 5;
sleep(2000);
end
else
while not Terminateddo
begin
Form1.PaintBox2.Canvas.MoveTo(X,Y);
Form1.PaintBox2.Canvas.LineTo(X,Y+H);
X := X + 5;
H := H + 5;
sleep(2000);
end
end;
end.

与上面线程写法的区别在于少了writeline函数,对paintbox的绘制在writepanelline里直接进行,没有用synchronize同步。这时启动两个线程时画线效果又不相同。
觉得比较奇怪,请帮忙看看
 
我想这应该是一个比较常见的问题吧,怎么没人解答呢
 
在sleep前调用一下移交控制权试一试
 
没错啊 NowPanelNumber放在thread之外是公用的他就等于2了当然只在paintbox2绘制了
NowPanelNumber: integer;放到private不就正常了吗
 
找到原因了,只需把画线单元WriteLineThread的变量
NowPanelNumber: integer;
X,Y,H: integer;
定义为线程WriteLine的private变量即可。这个时候这些变量才是相互独立的,互不影响。
嘿嘿,感觉像是一个低级错误。
现在问题已解决,但还有个不明白的地方,请教一下jamcky:你说的控制权是什么控制权,如何移交。谢谢
 
控制权就使把cpu控制权交给系统:
Application.ProcessMessages;
 
多人接受答案了。
 
后退
顶部