同步方法,我可以用它来不是主线程吗?

时间:2017-03-30 15:08:35

标签: delphi thread-synchronization

我很少使用线程,我对这个类有疑问:

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方法更改缓冲区。我是否正确使用了同步方法?

1 个答案:

答案 0 :(得分:7)

Synchronize()专门用于处理主UI线程。您可以使用它进行线程间同步,但所涉及的所有线程都必须使用它。在您的示例中,只有写入_buff的线程正在使用它,但是从_buff读取的线程不是。所以这是你逻辑上的漏洞。

话虽这么说,如果主UI线程不需要触摸您的数据,那么Synchronize()不是最佳解决方案。您可以使用同步对象来包装数据访问,例如TCriticalSectionTMutexTEventTMREWSyncSytem.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.