有一个TMemo控件,里面有N行数据。
我现在要写一个多线程的程序,假如有5个线程。
5个线程同时从TMemo读取数据。如:
TMemo有如下行:
123
456
789
234
345
567
线程T1读取了123
线程T2读取了456
线程T3读取了789
如何做到T1和T2不同时读取123。我现在是这样的,读取一行删一行,从后面向前读取。
比如567读取了,然后删掉。但是这样也会出现两个线程同时读取到了同一行。比如T1和T2同时都能读取到567。我现在用了TRTLCriticalSection,在读取TMemo先EnterCriticalSection读取完了再LeaveCriticalSection。
但是还是没用。有没有可能在一个线程操作TMemo控件的时候先把TMemo控件Lock,然后UnLock。哪位高手能赐教一二,写几段很简单的代码给小弟。分不多了,就剩下90分。
我现在要写一个多线程的程序,假如有5个线程。
5个线程同时从TMemo读取数据。如:
TMemo有如下行:
123
456
789
234
345
567
线程T1读取了123
线程T2读取了456
线程T3读取了789
如何做到T1和T2不同时读取123。我现在是这样的,读取一行删一行,从后面向前读取。
比如567读取了,然后删掉。但是这样也会出现两个线程同时读取到了同一行。比如T1和T2同时都能读取到567。我现在用了TRTLCriticalSection,在读取TMemo先EnterCriticalSection读取完了再LeaveCriticalSection。
但是还是没用。有没有可能在一个线程操作TMemo控件的时候先把TMemo控件Lock,然后UnLock。哪位高手能赐教一二,写几段很简单的代码给小弟。分不多了,就剩下90分。
每个线程取得控制权TRTLCriticalSection后,读取memo1.lines[p];并p:=p-1;再LeaveCriticalSection
所有线程要先取值然后到memo相应的行读取内容即可,因为取值函数加锁所以肯定正确,至于memo,不要随便改变其内容,因为这样肯定会影响其他线程
如果每个线程都是加锁成功才能操作memo,就不会出现这种情况了
先看下这个临界区怎么用
http://www.anxue.net/tech/shiping/DELPHI/2010/0414/32056_2.html比如 首先你已经声明好全局变量num=0(可以是static的),还有cs是临界区,注意临界区不能声明在线程里,要在你的主程序里
function getstr():string;
var
str:string;
begin
EnterCriticalSection(CS);
if (num>memo1.lines.count-1)
begin
str:='';
num:=-1;
end
else if (num<>-1)
begin
str:=memo1.lines[i];
num=num+1;
end;
LeaveCriticalSection(CS);
Result := str;
end;
while Form1.mmo1.Lines.Count <> Form1.ListBox1.Items.Count do
begin
str:= getstr; //调用函数,这个函数就是上面你写的。
if str <> '' then
Form1.ListBox1.Items.Add(str);
end;
function FUN(p:Pointer):DWORD; stdcall;
var
str:string;
begin
while Form1.mmo1.Lines.Count <> Form1.ListBox1.Items.Count do
begin
str:= getstr;
if str <> '' then
Form1.ListBox1.Items.Add(str);
end;
Result:= 0;
end;
FUN就是循环读取。
procedure TForm1.btn2Click(Sender: TObject);
var
ID: DWORD;
begin
itemidex:= 0;
CreateThread(nil, 0, @FUN, nil, 0, ID);
CreateThread(nil, 0, @FUN, nil, 0, ID);
CreateThread(nil, 0, @FUN, nil, 0, ID);
CreateThread(nil, 0, @FUN, nil, 0, ID);
CreateThread(nil, 0, @FUN, nil, 0, ID);
CreateThread(nil, 0, @FUN, nil, 0, ID);
end;
1
2
3
4
5
6
7
8
如果while str <> '' do
则读取出来的数据如下:
2
4
6
8
把你函数里面的if 和while换一下
if (Form1.mmo1.Lines.Count <> Form1.ListBox1.Items.Count) then
begin
str:= getstr;
while (str <> '')do
begin
Form1.ListBox1.Items.Add(str);
str:= getstr;
end;
Result:= 0;
end;
这样写的话貌似读取出来会有问题。
str:= getstr;
while str <> '' do
Form1.ListBox1.Items.Add(str);
每个线程,一旦获得控制权,就:顺序(还是逆序)读取整个lines?要不要删除?
临界中使用Memo1这些VCL控件,还是没用的.
操作Memo控件的地方使用synchronize或SendMessage
操作线程中全局变量的地方使用临界就行了
所以,工作线程操作vcl除了自己互斥外,还需要同步synchronize
这样不会冲突,但是我如果要删除的话就不太好解决了。