Threading and
P/Invoke
Tom Roeder
CS215 2006fa
Finalization
Recall C++ destructors:
~MyClass() {
// cleanup
}
called when object is deleted
does cleanup for this object
Don’t do this in C# (or Java)
similar construct exists
but only called on GC
no guarantees when
Finalization
More common idiom:
public void Finalize() {
base.Finalize();
Dispose(false);
}
maybe needed for unmanaged resources
slows down GC significantly
Finalization in GC:
when object with Finalize method created
add to Finalization Queue
when about to be GC’ed, add to Freachable Queue
Finalization
images from MSDN
Nov 2000
IDisposable and using
Idea for common cleanup
using(T t = new T()) {
// do work with t
} // t.Dispose is called by runtime
IDispose provides one method: void Dispose()
must provide finalizer, since must be called
when called from finalizer, don’t undo managed obj
often add private void Dispose(bool)
using calls Dispose automatically
used in class libraries, eg. for Socket
Weak References
Sometimes want to keep references but not cause
the GC to wait
MyClass c = new MyClass();
WeakReference wr = new WeakReference(c);
Now c can be collected
wr will return null if referenced after c collected
but to truly access the object, we get a strong ref
this is the Target property
Why?
Useful for large objects
infrequently accessed
nice to have but can be regenerated
Resurrection
Imagine assigning this to global in finalizer
object is now reachable again!
called “resurrection”
if finalizer already called, access unpredictable
Should not do this
but, if do, may want to reject accesses in methods
what would this finalize code do:
someObj = this;
System.GC.ReRegisterForFinalize()
System.GC
Can control the behavior of GC
not recommend in general
sometimes useful to give hints
Some methods:
Add/RemoveMemoryPressure
ReRegisterFor/SuppressFinalize
WaitForPendingFinalizers
Collect
Memory Profiles
Good
lots of small short-lived objects
or few but long-lived ones
few links between old and new objects
Bad
frequently create long-lived objects
create many objects that live a long but fixed
amount of time
unsafe mode
Sometimes need access to pointers
use unsafe modifier:
unsafe public void Method(out int* pi) {
int i = 10;
fixed(int* pj = &i) {
pi = pj;
}
}
what is wrong with this method?
unsafe modifier works a method modifier
or as a keyword for blocks
unsafe mode - Pointer details
Can only refer to “unmanaged” types
or enums
or structs composed of unmanaged types
Not a subclass of object
void* exists, but no arithmetic allowed
boxing/unboxing does not work
stackalloc gets memory from the stack
unsafe mode
Cannot be executed in untrusted context
pointer types
security requirement: so can’t change memory
eg. avoid stack smashing attacks
cannot refer to a reference
cannot refer to a struct that contains references
int* pi, pj;
// NOT int *pi, *pj;
Threading
Threading provides concurrent execution
Even useful on multiprocessor
As opposed to “sequential” execution
Comes at cost of overhead
Can be dangerous
For example
public int Increment(ref int x) { return ++x; }
What happens when called by two threads?
How to fix?
Threading
How to create a Thread
Create a new Thread instance with delegate
Type: public delegate void ThreadStart();
Call Start method
Let’s do an example on the board
Thread will be scheduled when possible
on SMP, may actually have many threads at once
on UP, still may be useful when blocked
as in UI, networking code, dealing with drivers
Threading
Need synchronization primitives
Way to ensure that only one thread executes
code in a region at once
Called “critical section”
C# provides (mostly in System.Threading)
lock statement
Monitor class
Interrupt
several others (see Birrell’s paper or MSDN)
Threading model: lock
Basic idea: each object has a lock
public int Increment(ref int x) {lock(this) return ++x;}
lock prevents more than one thread from entering
forces sequential order
What should we lock on?
for instance variables: this
for globals and statics: typeof(container)
something that will be same for all threads that
access this shared memory
Threading model: Monitor
Monitors provide synchronization construct
Monitor.Enter and Monitor.Exit
entry waits on a queue
waiting lets a new thread enter
same semantics as the lock construct
Why do we need both?
Gets a lock on the object
Cannot be used on value types: why not?
Threading model: Monitor
Methods
Monitor.Enter/Monitor.Exit
Monitor.Wait
enter/exit the monitor for a given object
wait on a given object
must be inside a monitor for that object
signal-delayed semantics
Monitor.Pulse/Monitor.PulseAll
some thread(s) can be released to try the monitor
Threading model: Interrupt
Sometimes need to wake up a thread
eg. if UI cancelled
eg. if event no longer needed
Standard OO way: exceptions
Interrupt causes thread to throw
ThreadInterruptedException
only on Wait or Sleep
Allows cleanup of invariants
Other synchro classes
Abort
Mutex and other synchronization
throws exception immediately
difficult to clean up: Why?
usually too draconian
good for interacting with Windows
but stick with lock and Monitor, normally
ReaderWriter Locks
not clear exactly what semantics they implement
Threading model: ThreadPool
Instead of explicitly creating threads
create a pool
pass delegates to worker threads
enqueued in pool
QueueUserWorkItem
takes a WaitCallback delegate
Good for large amounts of parallel work
eg. N-Body problem
automatically scales to number of processors
“embarrasingly parallel” problems
Threading Conclusions
Standard monitor semantics
useful constructions
as in Java
OS synchronization exposed
native ThreadPool
Really only need
lock
Monitor
P/Invoke
Use special attributes to make system calls
problems for C++
eg.
[DllImport(“kernel32”)]
static extern int GetProcessHeap();
calls to function in C library
name mangling: doesn’t match
General problem of COM/.NET interop
why does this matter?
COM Interoperability
Need metadata
Can then use COM class like .NET class
generated from TypeLib
even though major differences in models
eg. threading, registration, inheritance
useful for backwards compatibility
Can bind early or late to class
either we know its type at compile time or not
Calling a COM Server
namespace CallingCOMServer
{
using System;
using COMServerLib;
public class DotNET_COMClient
{...
public static int Main(string[] args)
{
MyCOMServer myS = new MyCOMServer();
return (myS.Add (17,4));
}
}
};
Late-Bound Activation
Use Reflection to get the type of the class
Can instantiate instance and call methods
ProgID / ClassID: looked up in registry
gives type of COM object
uses InvokeMethod to call methods
don’t have as strong type information here
COM object wrapped by __ComObject
can sometimes use as to get better info
Late-Bound
namespace LateBoundClient
{
using System.Reflection;
...
Type typ;
Object obj;
Object[] prms = new Object[2];
int r;
typ = Type.GetTypeFromProgID(„MyLib.MyServer");
obj = Activator.CreateInstance(typ);
prms[0] = 10;
prms[1] = 150;
r = (int)typ.InvokeMember(„aMethod",
BindingFlags.InvokeMethod, null, obj, prms);
...
}
.NET from COM
Needs to be public with public methods
Need to register a wrapper: use RegAsm tool
provides ProgID/ClassID information for registry
necessary for COM integration
Metadata must be converted to TypeLibrary
Have same early- and late-bound activation
early: by name
late: by ProgID/ClassID
Platform from .NET
Calling static functions in DLLs
P/Invoke provides services
Locates implementing DLL
Loads DLL
Finds function address
Fuzzy name matching algorithm
Pushes arguments on stack
Performs marshalling
Enables pre-emptive garbage collection
Transfers control to unmanaged code
P/Invoke Example
namespace HelloWorld
{
using System;
class MyClass
{
[dllimport(“user32.dll”, CharSet=CharSet.Ansi)]
static extern int MessageBox(int h, string m,
string c, int t);
0);
}
}
public static int Main()
{
return MessageBox(0, "Hello World!", "Caption",
}
P/Invoke Callbacks
Unmanaged code can call back to managed
code
Unmanaged parameter is function pointer
Must supply parameter as delegate
P/Invoke creates callback thunk
Passes address of thunk as callback parameter
Unmanaged Code
Managed Code
DLL
.NET Application
DLL function
Call passes pointer to
callback function
Implementation of callback
function
Callback Example
public class EnumReport
{
public bool Report(int hwnd, int lParam)
{ // report the window handle
Console.Write("Window handle is ");
Console.WriteLine(hwnd);
return true;
}
};
public class SampleClass
{
delegate bool CallBack(int hwnd, int lParam);
[DllImport("user32")]
static extern int EnumWindows(CallBack x, int y);
}
public static void Main()
{
EnumReport er = new EnumReport();
CallBack myCallBack = new CallBack(er.Report);
EnumWindows(myCallBack, 0);
}
Managed Extensions for C++
Allows C++ code to be managed by GC/CLR
compile with /clr: It Just Works
contains, eg
__gc, __box, __typeof, __interface, __property
#pragma managed/unmanaged
Very useful for native access to C++ libraries
generates MSIL from C++
build a “managed wrapper”
Partial conversion to managed code
© Copyright 2025 Paperzz