Wednesday 15 October 2008

Programming Progress

Over the past couple of days I've been tinkering with some programming, trying to get to grips with certain processes. Since I decided to look into tool development for this project I turned to C# and windows forms. I had a bash with them and it was so easy to knock some stuff together - the new guide system that helps you position your elements on the form is fantastic!

I know some stuff about C# but to develop any sort of audio application I really want to use FMOD as I'm so comfortable with it. There is an FMOD wrapper for C# but my familiarity with it lies in C++. After having a glance over FMOD# and its appalling lack of documentation I started to go off the idea of using C# at all until I read about using unmanaged code in it (Visual C# Unleashed 2005). This book explained how to load an unmanaged DLL into C# which would allow me to write my audio engine completely in C++, abstracting all but the necessary data which could be accessed through the exported DLL functions.

Sounded too good to be true so I began to do some simple tests. While I learned the basics quickly these simple tests didn't really give much to work with so I decided to take my growing networking module code and adapt it round a DLL wrapper. This was perfect. The code was complicated enough to give a good result (multiple threads, dynamic memory allocation etc.) and didn't need any extra work so I could get straight into C#.

So I defined my DLL export functions, loaded it into C# and Bobs your uncle, we have C++ being called from C#. I even managed to figure out how to debug in mixed mode so I could see what the values were in the C# and C++ code in the same project. All good things must come to an end though as I soon discovered a threading problem. Windows forms are very picky about threads. From what I've discovered, any thread you want to run in a windows form that requires access to UI elements needs to be created by the thread that made them ( see here ). This is also known as a single threaded apartment environment.

I deduced that this must be related to the thread I was running in my DLL to check for received packets over the network. I was wrong obviously as this thread doesn't need access to the forms ui. It turned out to be an issue with using BeginInvoke instead of just Invoke in the C# check-for-new-packets thread. I don't quite understand yet why BeginInvoke causes a deadlock until a new packet is received as all the research I've done on the two seems to indicate that it shouldn't. Hopefully I will find the answer someday.

No comments: