【发布时间】:2012-05-09 17:44:01
【问题描述】:
我有一个关于从不同线程调用方法的问题。好吧,我正在使用 WinUSB 驱动程序与 USB 设备进行通信。我有单独的线程从设备读取数据。设备命令在主线程中设置。实际上我正在使用 WinUSB_WritePipe 和 WinUSB_ReadPipe 方法来执行此类操作。在读取数据的线程中,我使用具有重叠结构和 WaitForMultipleObject 的异步读取方法。我的设备有一些我需要设置的功能,这是通过主线程中的 GUI 完成的。
我观察到一些奇怪的行为。我的问题是我是否需要锁定对这些方法的调用(例如,使用互斥锁),所以每次只有一个线程正在访问或调用方法。
旧方式:
type TMyThread = TThread
protected
procedure Execute; override;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
WinUsb_ReadPipe(Pipe, Amount, Overlapped)
ErrNo := GetLastError;
if ErrNo = ERROR_IO_PENDING then
begin
wRes = WaitForMultipleObjects(2, @HndEvt, false);
if wRes = WAIT_OBJECT_0 then
begin
ResetEvent(Overlapped.hEvent);
WinUSB_GetOVerlappedResult
DoSomethingWithData; // Do something
end;
end;
end;
end;
MainThread:
begin
// Set device sample rate
WinUSB_WritePipe (Pipe, Amount, Data, ...)
end;
新方式:
type TMyThread = TThread
protected
procedure Execute; override;
public
procedure Lock;
procedure Unlock;
constructor Create(ASuspended: boolean); override;
destructor Destroy; override;
end;
constructor TMyThread.Create(ASuspended: boolean);
begin
hMtx := CreateMutex(nil, false, nil);
end;
destructor TMyThread.Destroy(ASuspended: boolean);
begin
CloseHandle(hMtx);
end;
procedure TMyThread.Lock;
begin
WaitForSingleObject(hMtx, 10000);
end;
procedure TMyThread.Unlock;
begin
ReleaseMutex(hMtx);
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
Lock;
WinUsb_ReadPipe(Pipe, Amount, Overlapped)
Unlock;
ErrNo := GetLastError;
if ErrNo = ERROR_IO_PENDING then
begin
wRes = WaitForMultipleObjects(2, @HndEvt, false);
if wRes = WAIT_OBJECT_0 then
begin
ResetEvent(Overlapped.hEvent);
Lock;
WinUSB_GetOVerlappedResult
Unlock;
DoSomethingWithData; // Do something
end;
end;
end;
end;
MainThread:
begin
// Set device sample rate
Lock; // same mutex as in TMYThread
WinUSB_WritePipe (Pipe, Amount, Data, ...)
Unlock; // same mutex as in TMYThread
end;
这是非常简化的代码,其意图仅用于描述我的问题,并不反映我的编程技能。 :) 当然,我使用相同的互斥锁,然后在主线程中调用相同的方法。
我希望我尽可能简单地描述我的问题......再说一遍:我是否需要在不同的线程中锁定对这些方法的调用?
感谢您的时间和提前回答。我真的很感激!
兄弟,尼克斯
【问题讨论】:
-
您不需要锁定线程,您需要保护(例如通过锁定)线程之间的共享数据。在这种情况下,互斥锁有点重,关键部分就足够了。从主线程外的线程调用的所有 GUI 相关例程都需要同步。
-
我希望设备没有要求读取和写入是序列化的,所以这取决于你。您的读写线程是否使用设备的重叠区域?
-
提供的代码仅用于描述我的问题。我使用互斥锁是因为我正在使用 dll 并且我需要一些高级同步。我只想知道在调用它们之前是否需要锁定 WinUSB 方法。 WinUSB_ReadPipe 从两个不同的线程调用。我正在阅读不同线程中的不同管道。主线程仅用于命令,数据线程用于数据,因此管道不同。读取数据时,我使用重叠结构。发送命令和读取结果时,我不使用重叠结构。您认为驱动程序处理相同 WinUSB 方法的并发调用吗?
-
如果这篇文章的作者:microchip.com/forums/m437429-print.aspx 说实话,你不能从不同的线程使用winUSB。也就是说,我仍然不明白为什么需要 2 个线程来读取数据...
标签: multithreading delphi thread-safety delphi-2010 winusb