Question: I have a project where I need to load a Postscript font from disk. 
I found I could use "AddFontFile". Doing some research I see that I have to pipe the two fonts <http://msdn.microsoft.com/en-us/library/system.drawing.text.privatefontcollection.addfontfile.aspx> together so I tried: 

```
fontCollection = new PrivateFontCollection();
fontCollection.AddFontFile(@"C:\Temp\Font\myfont.PFM|C:\Temp\Font\myfont.PFB");

```

I'm getting a a error "Illegal characters in path".
I'm not sure if I'm piping the two fonts correctly.

Any help would be great, I should mention we are still on XP not sure if that makes a differnts or not.

Mike

Answer: 
> 
> But it seems to me that both are too much effort.
> 
> 
> 

If you want it to work with wait handles, that's what you'll have to do. But if all you need is something that will block until all of the threads have finished, you can use a [Semaphore](http://msdn.microsoft.com/en-us/library/windows/desktop/ms685129%28v=vs.85%29.aspx) or perhaps a [Synchronization Barrier](http://msdn.microsoft.com/en-us/library/windows/desktop/hh706897%28v=vs.85%29.aspx).
With the [answer from Jim Mischel](https://stackoverflow.com/a/18969556/237483) I found a solution. [Semaphore Objects](http://msdn.microsoft.com/en-us/library/windows/desktop/ms685129%28v=vs.85%29.aspx) can solve two issues:

* Waiting for all threads
* Limiting the number of running threads

This is a small, self contained example:

```
#include <iostream>
#include <vector>
#include <windows.h>

static const LONG SEMCOUNT = 3;

DWORD CALLBACK ThreadProc(void* vptr)
{
    HANDLE* sem = (HANDLE*)vptr; 
    Sleep(10000);
    ReleaseSemaphore(*sem, 1, NULL);
    return 0;
}

int main()
{
    HANDLE semh = CreateSemaphore(NULL, SEMCOUNT, SEMCOUNT, 0);

    // create 10 threads, but only SEMCOUNT threads run at once
    for (int i = 0; i < 10; i++)
    {
        DWORD id;
        WaitForSingleObject(semh, INFINITE);
        HANDLE h = CreateThread(NULL, 0, ThreadProc, (void*)&semh, 0, &id);
        if (!h)
            CloseHandle(h);
    }

    // wait until all threads have released the semaphore
    for (LONG j = 0; j < SEMCOUNT; j++)
    {
        WaitForSingleObject(semh, INFINITE);
        std::cout << "Semaphore count = " << j << std::endl;
    }

    std::cout << "All threads terminated" << std::endl;

    return 0;
}

```