我很少使用线程,我对这个类有疑问:
class TopCategories extends React.Component {
render() {
const Tab = () => (
<TestBtn key={this.props.key} >
testText {this.props.content}
</TestBtn>
)
const items = [
{ id: 1, name: 'tab-1', text: 'text' },
{ id: 2, name: 'tab-2', text: 'text' },
{ id: 3, name: 'tab-3', text: 'text' },
{ id: 4, name: 'tab-4', text: 'text' },
{ id: 5, name: 'tab-5', text: 'text' },
]
const tabs = items.map(item =>
<Tab key={item.id} content={item.name} />,
)
return (
<Container>
<Wrapper>
{tabs}
</Wrapper>
</Container>
)
}
}
export default TopCategories
如果任何模式与超时缓冲区匹配,则线程必须解密。但是其他线程(NOT MAIN)可以使用BuffUpdate方法更改缓冲区。我是否正确使用了同步方法?
答案 0 :(得分:7)
Synchronize()
专门用于处理主UI线程。您可以使用它进行线程间同步,但所涉及的所有线程都必须使用它。在您的示例中,只有写入_buff
的线程正在使用它,但是从_buff
读取的线程不是。所以这是你逻辑上的漏洞。
话虽这么说,如果主UI线程不需要触摸您的数据,那么Synchronize()
不是最佳解决方案。您可以使用同步对象来包装数据访问,例如TCriticalSection
,TMutex
,TEvent
,TMREWSync
,Sytem.TMonitor
等。例如:
unit ExpectingThread;
interface
uses
System.Classes, System.SyncObjs;
type
TExpectingThread = class(TThread)
private
_timeoutMs: Integer;
_buff: string;
_buffLock: TCriticalSection;
_buffChanged: Boolean;
_patterns: TArray<string>;
_result: Integer;
function Timeouted(startTime: Cardinal): Boolean;
function ExpectedDetected: Boolean;
protected
procedure Execute; override;
public
constructor Create(patterns: TArray<string>; buff: string; timeoutMs: Integer);
destructor Destroy; override;
//this method is called from other NOT MAIN thread
procedure BuffUpdate(text: string);
end;
implementation
uses
Winapi.Windows, System.RegularExpressions;
{ TExpectingThread }
constructor TExpectingThread.Create(patterns: TArray<string>; buff: string; timeoutMs: Integer);
begin
inherited Create(False);
_buffLock := TCriticalSection.Create;
_patterns := patterns;
_timeoutMs := timeoutMs;
_buff := buff;
_buffChanged := True;
end;
destructor TExpectingThread.Destroy;
begin
_buffLock.Free;
inherited;
end;
//this method is called from other NOT MAIN thread
procedure TExpectingThread.BuffUpdate(text: string);
begin
_buffLock.Enter;
try
_buff := _buff + text;
_buffChanged := True;
finally
_buffLock.Leave;
end;
end;
procedure TExpectingThread.Execute;
var
startTime: DWORD;
begin
startTime := GetTickCount;
while not Terminated do
begin
if Timeouted(startTime) then
begin
Self.ReturnValue := 0; // timeouted
Exit;
end;
if ExpectedDetected then
begin
Self.ReturnValue := 1; // found
Exit;
end;
end;
end;
function TExpectingThread.ExpectedDetected: Boolean;
var
i: Integer;
buff: string;
begin
Result := False;
_buffLock.Enter;
try
If not _buffChanged then Exit;
buff := _buff;
UniqueStr(buff);
_buffChanged := False;
finally
_buffLock.Leave;
end;
for i := Low(_patterns) to High(_patterns) do
begin
if TRegEx.IsMatch(buff, _patterns[i]) then
begin
_result := i;
Exit(True);
end;
end;
end;
function TExpectingThread.Timeouted(startTime: Cardinal): Boolean;
var
currentTime: DWORD;
begin
currentTime := GetTickCount;
result := currentTime - startTime > _timeoutMs;
end;
end.