The problem does not sound complicated enough to warrant worrying about
specific design patterns at all.
The real issue here (as I understand it) is that you apparently have an
API that provides only async methods, with no synchronous equivalents.
So basically, you need to turn those into synchronous methods.
it is not clear from your post where the events live relative to the
object on which you are calling the method to invoke a command. So I will
gloss over that bit and not worry about it. I assume you can fill in
the details.
I think one of the easiest ways to address the issue would be to simply
have a queue of the commands. Make the Action delegate references if
you like, whatever???does not matter too much.
Then just subscribe to both events, and in the event handler, signal the
consumer of the queue to peek at the next command if present and invoke
it. When queuing a command, if the queue is empty, you can just invoke
the command immediately.
I suggested using peek to get the command; do not dequeue the command
until it is actually been completed. This gives you a way to know
whether a command is in progress when you queue a new one. If you would
prefer to dequeue the command right away, then just keep a flag around
that is set when there is a command in progress, so you can tell when an
empty queue means you can actually invoke the command immediately or not.
Another way to approach this, of course, would be to just wrap the async
API in something that gives you a synchronous version. In that wrapper,
you would have synchronous versions of your command methods, which when
called simply wait for the event to be raised signaling the completion
of the command, and only return to the caller when that event is raised.
The wrapper approach might be slightly less efficient, but it does have
the advantage of being a little simpler, and also of having a lower
memory footprint (because it does not have to maintain the queue, which
could get quite large if the latency on your hardware is much higher
than your file i/o and the list of commands is itself very large).
Pete