Warum ist die Entercriticalsection nicht das Timing?C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Warum ist die Entercriticalsection nicht das Timing?

Post by Anonymous »

Aus der Dokumentation zur EntercriticalSection :

kann diese Funktion exception_possible_deadlock erhöhen, auch als status_possible_deadlock bekannt, wenn ein Wartenoperium in den kritischen Abschnitten aus der Abteilung ausgeht. Das Zeitüberschreitungsintervall wird durch den folgenden Registrierungswert angegeben: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ CriticalSectionTimeout . Behandeln Sie keine mögliche Deadlock -Ausnahme; Debuggen Sie stattdessen die Anwendung. Zu diesem Zweck habe ich ein kleines C# -Skript mit Vanara (.NET-Wrappers über WinAPI-Funktionen) erstellt: < /p>
#r "nuget: Vanara.PInvoke.Kernel32, 4.1.6"
#r "nuget: System.CommandLine, 2.0.0-beta5.25306.1"

using System.CommandLine;
using System.Diagnostics;
using System.Threading;
using static Vanara.PInvoke.Kernel32;

var sleepMillisecondsOption = new Option("--sleep-milliseconds", "-s") { DefaultValueFactory = (_) => 5000 };
var rootCommand = new RootCommand("Critical section contention") { sleepMillisecondsOption };
rootCommand.SetAction(parseResult => Runner(parseResult.GetValue(sleepMillisecondsOption)));

return new CommandLineConfiguration(rootCommand).Invoke(Args.ToArray());

void Runner(int sleepMilliseconds)
{
var startTime = Stopwatch.GetTimestamp();
InitializeCriticalSection(out var criticalSection);
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: Started");
var thread1 = new Thread(Worker);
var thread2 = new Thread(Worker);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: Finished");

void Worker()
{
var threadId = Thread.CurrentThread.ManagedThreadId;
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: {threadId}: Before EnterCriticalSection");
EnterCriticalSection(ref criticalSection);
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: {threadId}: After EnterCriticalSection");
Thread.Sleep(sleepMilliseconds);
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: {threadId}: Before LeaveCriticalSection");
LeaveCriticalSection(ref criticalSection);
WriteLine($"{Stopwatch.GetElapsedTime(startTime)}: {threadId}: After LeaveCriticalSection");
}
}
< /code>
und kompilierte es in eine in sich geschlossene ausführbare Datei auf .NET 8: < /p>
dotnet script publish -c Release ContendCriticalSection.csx
< /code>
Wenn ich es auf meinem Computer ausführe (Windows 11, 26100.4349), erzeugt es die erwartete Ausgabe: < /p>
00:00:00.0001706: Started
00:00:00.0020008: 4: Before EnterCriticalSection
00:00:00.0021132: 5: Before EnterCriticalSection
00:00:00.0023623: 4: After EnterCriticalSection
00:00:05.0078115: 4: Before LeaveCriticalSection
00:00:05.0082580: 5: After EnterCriticalSection
00:00:05.0084024: 4: After LeaveCriticalSection
00:00:10.0122947: 5: Before LeaveCriticalSection
00:00:10.0126381: 5: After LeaveCriticalSection
00:00:10.0130023: Finished
< /code>
Dann habe ich eine Windows -Instanz auf EC2 (Windows Server 2025 Datacenter, 26100.4061) erstellt, den Registrierungswert auf 2 geändert und die Instanz neu gestartet: < /p>
PS C:\Users\Administrator> reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager" /v CriticalSectionTimeout

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager
CriticalSectionTimeout REG_DWORD 0x2
< /code>
Ich habe erwartet, dass der zweite Thread die Ausnahme nach zwei Sekunden erhöht, aber das Ausführen der ausführbaren Datei auf der EC2 -Instanz erzeugt die gleiche Ausgabe: Beide Threads werden 5 Sekunden lang abkunden und dann normal zurückkehren. Das gleiche passiert, wenn ich die ausführbare Datei mit größeren Schlafeinstellungen ausführe: Der kritische Abschnitt nicht aus dem Timeout. Der Registrierungswert
HKLM \ System \ currentControlSet \ Control \ SessionManager \ CriticalSectionTimeout < /p>
Das Gerät für diesen Wert ist in Sekunden. Sie müssen einen Wert
$ cmp ContendCriticalSection.original.exe ContendCriticalSection.patched.exe -b

ContendCriticalSection.original.exe ContendCriticalSection.patched.exe differ: byte 6407525, line 16506 is 0 ^@ 2 ^B
< /code>
Die gepatchte Anwendung scheint auch diesen Wert nicht zu betrachten, und ihre Ausgabe ist der gleiche: Der zweite Thread wartet 5 Sekunden lang, ohne Ausnahmen zu werfen. Der Debugger gibt nämlich weitere Debugging -Nachrichten aus: < /p>
RTL: Enter CriticalSection Timeout (0 secs) 0
RTL: Pid.Tid 00000000000088AC.0000000000000EC8, owner tid 000000000000A818 Critical Section 0000016D92CBCAD8 - ContentionCount == 1
RTL: Re-Waiting
RTL: Enter CriticalSection Timeout (0 secs) 1
RTL: Pid.Tid 00000000000088AC.0000000000000EC8, owner tid 000000000000A818 Critical Section 0000016D92CBCAD8 - ContentionCount == 1
RTL: Re-Waiting
RTL: Enter CriticalSection Timeout (0 secs) 2
RTL: Pid.Tid 00000000000088AC.0000000000000EC8, owner tid 000000000000A818 Critical Section 0000016D92CBCAD8 - ContentionCount == 1
RTL: Re-Waiting
< /code>
Anscheinend versucht der zweite Thread automatisch, den kritischen Abschnitt in den Blöcken wieder aufzunehmen: 3-mal, dann 9 Mal, dann 90-mal und dann 900 Mal. Es scheint eine 2-Sekunden-Verzögerung zwischen den Blöcken und eine Verzögerung von ~ 10 ms zwischen den Versuchen zu geben. Diese Umgebung und der zweite Thread wartet immer noch auf den kritischen Abschnitt.>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post