Ok, je n'arrive pas à me faire une idée correcte des scénarios de multithreading. Désolé de poser à nouveau une question similaire, mais je vois beaucoup de "faits" différents sur Internet.
public static class MyClass {
private static List<string> _myList = new List<string>;
private static bool _record;
public static void StartRecording()
{
_myList.Clear();
_record = true;
}
public static IEnumerable<string> StopRecording()
{
_record = false;
// Return a Read-Only copy of the list data
var result = new List<string>(_myList).AsReadOnly();
_myList.Clear();
return result;
}
public static void DoSomething()
{
if(_record) _myList.Add("Test");
// More, but unrelated actions
}
}
L'idée est que si l'enregistrement est activé, les appels à DoSomething() sont enregistrés dans une liste interne, et retournés lorsque StopRecording() est appelé.
Mon cahier des charges est le suivant :
- StartRecording n'est pas considéré comme Thread-Safe. L'utilisateur doit l'appeler pendant qu'aucun autre Thread n'appelle DoSomething(). Mais si cela pouvait être le cas, ce serait formidable.
- StopRecording n'est pas non plus officiellement thread-safe. Encore une fois, ce serait formidable s'il pouvait l'être, mais ce n'est pas une obligation.
- DoSomething doit être à l'abri des threads.
La méthode habituelle semble être :
public static void DoSomething()
{
object _lock = new object();
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Une autre solution consiste à déclarer une variable statique :
private static object _lock;
public static void DoSomething()
{
lock(_lock){
if(_record) _myList.Add("Test");
}
// More, but unrelated actions
}
Cependant, cette réponse précise que cela n'empêche pas un autre code d'y accéder.
Je me demande donc
- Comment verrouiller correctement une liste ?
- Dois-je créer l'objet de verrouillage dans ma fonction ou comme une variable de classe statique ?
- Puis-je également intégrer la fonctionnalité de Start et StopRecording dans un lock-block ?
- StopRecording() fait deux choses : Mettre une variable booléenne à false (pour empêcher DoSomething() d'ajouter plus de choses) et ensuite copier la liste pour retourner une copie des données à l'appelant). Je suppose que _record = false ; est atomique et prend effet immédiatement ? Donc, normalement, je n'aurais pas à m'inquiéter du Multi-Threading ici du tout, à moins qu'un autre Thread appelle StartRecording() à nouveau ?
En fin de compte, je cherche un moyen d'exprimer "Ok, cette liste est la mienne maintenant, tous les autres fils doivent attendre jusqu'à ce que j'en aie fini avec elle".