Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

if (lastErrorCode == (uint)ERROR_FILE_NOT_FOUND)

{

//Deal with error

}

System Error Codes can be found here:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

GetLastError API

There is a native GetLastError API which you can use as well :

[DllImport("coredll.dll", SetLastError=true)] static extern Int32 GetLastError();

When calling Win32 API from managed code, you must always use the Marshal.GetLastWin32Error.

Here's why:

Between your Win32 call which sets the error (calls SetLastError), the CLR can call other Win32 calls which could call SetLastError as well, this behavior can override your error value. In this scenario, if you call GetLastError you can obtain an invalid error.

Setting SetLastError = true, makes sure that the CLR retrieves the error code before it executes other Win32 calls.

Section 155.7: Pinned Object

GC (Garbage Collector) is responsible for cleaning our garbage.

While GC cleans our garbage, he removes the unused objects from the managed heap which cause heap fragmentation. When GC is done with the removal, it performs a heap compression (defragmintation) which involves moving objects on the heap.

Since GC isn't deterministic, when passing managed object reference/pointer to native code, GC can kick in at any time, if it occurs just after Inerop call, there is a very good possibility that object (which reference passed to native) will be moved on the managed heap - as a result, we get an invalid reference on managed side.

In this scenario, you should pin the object before passing it to native code.

Pinned Object

Pinned object is an object that is not allowed to move by GC.

Gc Pinned Handle

You can create a pin object using Gc.Alloc method

GCHandle handle = GCHandle.Alloc(yourObject, GCHandleType.Pinned);

Obtaining a pinned GCHandle to managed object marks a specific object as one that cannot be moved by GC, until freeing the handle

Example:

[DllImport("kernel32.dll", SetLastError = true)]

GoalKicker.com – C# Notes for Professionals

747

public static extern void EnterCriticalSection(IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]

public static extern void LeaveCriticalSection(IntPtr ptr);

public void EnterCriticalSection(CRITICAL_SECTION section)

{

try

{

GCHandle handle = GCHandle.Alloc(section, GCHandleType.Pinned); EnterCriticalSection(handle.AddrOfPinnedObject());

//Do Some Critical Work

LeaveCriticalSection(handle.AddrOfPinnedObject());

}

finaly

{

handle.Free()

}

}

Precautions

When pinning (especially large ones) object try to release the pinned GcHandle as fast as possible, since it interrupt heap defragmentation.

If you forget to free GcHandle nothing will. Do it in a safe code section (such as finaly)

Section 155.8: Simple code to expose class for com

using System;

using System.Runtime.InteropServices;

namespace ComLibrary

{

[ComVisible(true)]

public interface IMainType

{

int GetInt();

void StartTime();

int StopTime();

}

[ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] public class MainType : IMainType

{

private Stopwatch stopWatch;

public int GetInt()

{

return 0;

}

public void StartTime()

{

stopWatch= new Stopwatch(); stopWatch.Start();

}

GoalKicker.com – C# Notes for Professionals

748

public int StopTime()

{

return (int)stopWatch.ElapsedMilliseconds;

}

}

}

GoalKicker.com – C# Notes for Professionals

749