Wir versuchen, Informationen von einem Hardwaregerät zu lesen, und die einzige Möglichkeit, dies zu tun, besteht darin, über eine geschlossene native DLL, die der Hardwarehersteller bereitstellt, mit ihr zu kommunizieren. Sie bieten auch eine .NET-Wrapper die DLL zuzugreifen, die die Wrappermethode Besorgnis unter vereinfacht:Gleicher Thread gibt die Methode vor dem Verlassen erneut ein
[DllImport("hardware_mfg.dll")]
private static extern int hardware_command_unicode(MarshalAs(UnmanagedType.LPWStr)] string outdata, uint outcount, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder indata, uint maxdata, ref uint incount);
public static int HardwareCommand(string senddata, StringBuilder recdata)
{
uint incount = 0;
return HardwareWrapper.hardware_command_unicode(senddata, (uint)senddata.Length, recdata, (uint)recdata.Capacity, ref incount);
}
Der Code der HardwareWrapper.HardwareCommand Aufruf der Funktion ist:
// This method gets called from a DispatcherTimer.Tick event
public static int SendCommand(string command, StringBuilder buffer)
{
lock (_locker)
{
try
{
if (_commandInProgress)
{
// This exception gets thrown
throw new InvalidOperationException("This should not be possible");
}
_commandInProgress = true;
// InvalidOperationException gets thrown while previous call to HardwareCommand here has not yet returned
var result = HardwareWrapper.HardwareCommand(command, buffer);
return result;
}
finally
{
_commandInProgress = false;
}
}
}
Das verwirrende Teil ist dass die InvalidOperationException ausgelöst wird. Wenn der Hauptthread in var result = HardwareWrapper.HardwareCommand(...)
eintritt, ist es möglich, die Methode erneut aufzurufen und die gleiche Funktion einzugeben, bevor der erste Aufruf zurückgegeben wird. Es ist zeitweise, dass die Ausnahme ausgelöst wird, aber die Ausführung dieses Codes für 15-30 Sekunden reicht aus, um die Ausnahme passieren zu lassen.
- Wie ist es möglich, dass der Haupt-Thread zweimal in einer Methode existiert?
- Was kann getan werden, um dies zu verhindern?
EDIT 1: Verschieben Sperre äußeren Umfang
Wiederkehrende Anrufe sind ziemlich normal. Funktion A ruft Funktion B auf, die Funktion A aufruft. Das ist, was Sie haben. Vermutlich führt 'HardwareWrapper.HardwareCommand' dazu, dass das Timer-Tick-Ereignis erneut ausgelöst wird. –
HardwareWrapper.HardwareCommand ist nicht verwalteter Code und ruft SendCommand nicht auf oder löst das Timer-Tick-Ereignis aus. Das DispatcherTimer-Ereignis kann erneut ausgelöst werden, während sich der Hauptthread im nicht verwalteten Code befindet. Aber sollte der Hauptthread nicht warten, bis der nicht verwaltete Code zurückgegeben wird, bevor diese Methode erneut aufgerufen wird? – Clark
Sind Sie sicher, dass es keine Wettlaufbedingung ist, wenn die 'Tick' erneut ausgeführt wird, bevor' finally' eingegeben und das Flag zurückgesetzt wird? Versuchen Sie, das Flag innerhalb der 'Sperre' zurückzusetzen – slawekwin