CRITICAL_SECTION in c#

落爺英雄遲暮 提交于 2019-12-25 06:28:16

问题


All. I need to use winapi critical section in c# code.

First of all, I import functions:

[StructLayout(LayoutKind.Sequential)]
public struct CRITICAL_SECTION { public int dummy; }

// INIT CRITICAL SECTION
[DllImport("kernel32.dll")]
static extern bool InitializeCriticalSectionAndSpinCount(ref CRITICAL_SECTION
   lpCriticalSection, uint dwSpinCount);

// DELETE CRITICAL SECTION
[DllImport("kernel32.dll")]
static extern void DeleteCriticalSection(ref CRITICAL_SECTION
   lpCriticalSection);

// ENTER CRITICAL SECTION
[DllImport("kernel32.dll")]
static extern void EnterCriticalSection(ref CRITICAL_SECTION
   lpCriticalSection);

// LEAVE CRITICAL SECTION
[DllImport("kernel32.dll")]
static extern void LeaveCriticalSection(ref CRITICAL_SECTION
   lpCriticalSection);

In this way I try to use critical section:

static void Main(string[] args)
            {
                GenerateArray();

                InvokeThread invokeThread = () =>
                {
                    WaitForSingleObject(ghSemaphore, 0);
                    EnterCriticalSection(ref CriticalSection);   // critical section

                    int[] array = new int[ARRAY_SIZE_PER_THREAD];
                    int baseI = thread * ARRAY_SIZE_PER_THREAD;
                    for (int i = 0; i < ARRAY_SIZE_PER_THREAD; ++i)
                    {
                        array[i] = gList[baseI + i];
                    }

                    LeaveCriticalSection(ref CriticalSection);       // critical section
                    ReleaseSemaphore(ghSemaphore, 1, IntPtr.Zero);

                    return 0;
                };

                ghSemaphore = CreateSemaphore(ref seqAttr, THREADS_NUMBER, THREADS_NUMBER, "");
                InitializeCriticalSectionAndSpinCount(ref CriticalSection, 0);                           

                IntPtr threadPtr = Marshal.GetFunctionPointerForDelegate(invokeThread);

                IntPtr[] handlers = new IntPtr[THREADS_NUMBER];
                for (int i = 0; i < THREADS_NUMBER; ++i)
                {
                    int handle = CreateThread(IntPtr.Zero, 0, threadPtr, IntPtr.Zero, 0, 0);
                    handlers[i] = new IntPtr(handle);
                }

                WaitForMultipleObjects(THREADS_NUMBER, handlers, true, Infinite);    
                DeleteCriticalSection(ref CriticalSection); // delete critical section
            }
        }

But at next line gList containes wrong values. And every thing is good, if I don't use critical section.

for (int i = 0; i < ARRAY_SIZE_PER_THREAD; ++i)
{
    array[i] = gList[baseI + i];
}

Where could be a problem?


回答1:


Your definition of the CRITICAL_SECTION struct is wrong. In the Windows headers is has 24 bytes or so, but yours has only 4.

Also, you don't do new CRITICAL_SECTION anywere. And you need it, InitializeCriticalSection sets the data, but don't allocate it.




回答2:


I also agree that using the critical section API from .net seems like a bad design choice. If you must then I'd contemplate writing a C++/CLI mixed-mode wrapper. That way you can include the windows header files directly.

However, there is a rather obvious flaw in your p/invoke code. That's the declaration of the CRITICAL_SECTION struct. You've declared it as holding a single integer value. But the native struct is bigger than that. On x86 it is 24 bytes long, and on x64 it is 40 bytes long. You don't need to declare any of the fields since from your perspective it's just an opaque block of memory.

If I were you I would get rid of CRITICAL_SECTION. I would change all the ref CRITICAL_SECTION parameters to IntPtr. And I would use Marshal.AllocHGlobal(40) to create a large enough block of memory to hold the critical section data.

For example:

[DllImport("kernel32.dll")]
static extern bool InitializeCriticalSectionAndSpinCount(
    IntPtr lpCriticalSection, 
    uint dwSpinCount
);

and so on.



来源:https://stackoverflow.com/questions/14156349/critical-section-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!