Я не понимаю, что вызывает эту ошибку
[DllImport("kernel32.dll")]
static extern void EnterCriticalSection(ref IntPtr lpCriticalSection);
[DllImport("kernel32.dll")]
static extern void LeaveCriticalSection(ref IntPtr lpCriticalSection);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
unsafe
{
try
{
IntPtr criticalSection = new IntPtr();
EnterCriticalSection(ref criticalSection);
LeaveCriticalSection(ref criticalSection);
}
catch (AccessViolationException exception)
{
Console.WriteLine(exception.Message);
}
}
}
Пробовал в Visual Studio изменить тип сборки с Any CPU на x86, но результатов это не принесло.
Вам действительно нужна низкоуровневая критическая секция? C# имеет встроенные функции синхронизации, такие как lock.
прочитать инструкцию learn.microsoft.com/en-us/windows/win32/api/synchapi/…





EnterCriticalSection() ожидает получить указатель на структуру CRITICAL_SECTION, которая была инициализирована с помощью InitializeCriticalSection() или InitializeCriticalSectionAndSpinCount().
Но вместо этого вы даете ему ссылку на неинициализированный IntPtr, который не указывает ни на что значимое. Отсюда и сбой, когда EnterCriticalSection() пытается получить доступ к несуществующей структуре.
Правильный код должен выглядеть примерно так:
[StructLayout(LayoutKind.Sequential)]
public struct CRITICAL_SECTION
{
public IntPtr DebugInfo;
public int LockCount;
public int RecursionCount;
public IntPtr OwningThread;
public IntPtr LockSemaphore;
public UIntPtr SpinCount;
}
[DllImport("kernel32.dll")]
static extern void InitializeCriticalSection(ref CRITICAL_SECTION lpCriticalSection);
[DllImport("kernel32.dll")]
static extern void DeleteCriticalSection(ref CRITICAL_SECTION lpCriticalSection);
[DllImport("kernel32.dll")]
static extern void EnterCriticalSection(ref CRITICAL_SECTION lpCriticalSection);
[DllImport("kernel32.dll")]
static extern void LeaveCriticalSection(ref CRITICAL_SECTION lpCriticalSection);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
unsafe
{
try
{
CRITICAL_SECTION criticalSection = new CRITICAL_SECTION();
InitializeCriticalSection(ref criticalSection);
EnterCriticalSection(ref criticalSection);
LeaveCriticalSection(ref criticalSection);
DeleteCriticalSection(ref criticalSection);
}
catch (AccessViolationException exception)
{
Console.WriteLine(exception.Message);
}
}
}
Однако вам действительно не нужно использовать CRITICAL_SECTION в C#, вместо этого используйте оператор блокировки или примитив синхронизации , например System.Threading.Monitor.
Будет ли это работать вообще, если GC решит переместить структуру между вызовами? т.е. stackoverflow.com/a/3269274/11683.
struct — это тип значения, его нельзя перемещать, только копировать (но в документах CRITICAL_SECTION говорится, что его нельзя копировать или перемещать). CRITICAL_SECTION содержит в качестве членов только другие типы значений. Таким образом, он не подлежит сборке мусора, если только он не содержится как член типа объекта, тогда содержащий объект удаляется сборщиком мусора.
Во-первых, вы должны удалить
refs. Во-вторых, вы не можете войти в критическую секцию, которая не была инициализирована. В-третьих, вам не нужно использовать критические секции в C#.