First, I fully support ApochPiQ's warning about parallel programming. It adds a whole new dimension to hunting bugs. If this is your first foray into it, be forewarned of the early gray hair, if you don't pull it out in frustration first.
With that in mind, let's set about answering your question.
If you are ready for it, the easiest toe-dipping into those murky waters is to use library-provided asynchronous calls.
The safest calls are the asynchronous calls where you issue the command and get a task ID back. You can create a collection of all the task IDs from all your calls. Then you can poll the system back to see if each task ID has completed. If you get a response like E_NOTREADY or E_WOULDBLOCK or whatever the response is for your system, then you continue doing other stuff and come back later. Eventually all the tasks should have a return code that they completed successfully or failed. This is safest because you aren't touching any of the concurrency stuff. Your own code lives within its own single thread.
After that, the next safest are asynchronous calls that you provide a callback function when you start the task. This is a little more tricky because you don't know when the callback function will be called. The callback function could be called in the middle of another callback function. If you're maintaining a list of tasks you need to be careful with locking around your callback functions since it may be possible that it is called by multiple tasks finishing at exactly the same time. If two items are trying to remove each other from the task list container at the same time and you don't have a proper system in place to handle the concurrency it can corrupt your collection. Since you're using c# you can either use it's built-in locking mechanism after reading up on how to do it properly, or if you can meet the requirements in your usage, you can use one of the built-in containers like ConcurrentDictionary.
Beyond that you start entering the realm of using locks within your own code. There have been many excellent books and tutorials written on them, Google can help. It takes a certain level of experience before you want to add that to your code. It is a minefield with an untold number of ways to accidentally harm your program.
i googoled and i saw a little of task programming.
I have this scenario:
i have many events that fire and i must create a task in response to them and launch the task if another single task of general importation has finished his work.
When all the tasks of events have finished his work i can launch the general task and so one.
I saw that the key commands are async and await , but i don't understand how get the response id from the launched task and insert it in a list, i saw that these task return a string or other generic type.