Analyse des points d'utilisation abusive dans la programmation multithread .Net

怪我咯
Libérer: 2017-04-10 10:59:31
original
1949 Les gens l'ont consulté

Cet article présente principalement l'analyse des points d'utilisation abusive dans la programmation multithread .Net. Il a une certaine valeur de référence, jetons un coup d'oeil avec l'éditeur ci-dessous

1 Problème de variable partagée

Mauvaise écriture :

Toutes les tâches peuvent partager la même variable, donc les résultats de sortie peuvent être les mêmes.

public static void Error()
{
   for(int i=0;i<10;i++)
   {
    Task.Run(() => { Console.WriteLine("{0}", i); });
   }
}
Copier après la connexion

Écriture correcte :

Attribuer la variable i à la variable locale temp , afin que chaque tâche utilise une valeur i différente.

public static void Right()
{
   for (int i = 0; i < 10; i++)
   {
    int temp = i;
    Task.Run(() => { Console.WriteLine("{0}", temp); });
   }
}
Copier après la connexion

2 Ne pas nettoyer les ressources requises pour les tâches en attente

Mauvaise écriture :

Sortez du contenu texte de manière asynchrone, donc avant d'utiliser StreamReader, la variable sr a quitté sa portée et la méthode Dispose est appelée.

public static void Error()
{
   using (StreamReader sr = new StreamReader(@"D:\说明.txt", Encoding.Default))
   {
    Task.Run(() => { Console.WriteLine("输出:{0}",sr.ReadLine()); });
   }
}
Copier après la connexion

Écriture correcte :

public static void Right()
{
   using (StreamReader sr = new StreamReader(@"D:\说明.txt", Encoding.Default))
   {
    var task = Task.Run(() => { Console.WriteLine("输出:{0}", sr.ReadLine()); });
    task.Wait();
   }
}
Copier après la connexion

3 Évitez de verrouiller ceci, typeof(type), string

La bonne approche : définissez un champ privé en lecture seule de type objet et verrouillez-le.

4 Le nombre de waitHandles dans WaitHandle.WaitAll doit être inférieur ou égal à 64

public static void Error()
{
   ManualResetEvent[] manualEvents = new ManualResetEvent[65];

   try
   {
    for (int i = 0; i < 65; i++)
    {
     var temp = i;
     Task.Run(() =>
     {
      manualEvents[temp] = new ManualResetEvent(false);
      Console.WriteLine("{0}", temp);
      manualEvents[temp].Set();
     });
    }
    WaitHandle.WaitAll(manualEvents);
   }
   catch (Exception ae)
   {
    Console.WriteLine(ae.Message);
   }
}
Copier après la connexion

5 Impossible d'intercepter l'exception

try
{
    var task = Task.Run(() => { throw new Exception("抛异常"); });
    //如果将下面这行代码注掉,则无法抛出异常
    task.Wait();
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}
Copier après la connexion

6 Les ressources de la tâche doivent-elles être libérées

<🎜 ? > Il est recommandé d'appeler Dispose, mais ne pas appeler n'est pas une erreur grave.

Notez que les ressources ne sont pas autorisées à être libérées lorsque la tâche est dans certains états, sinon une erreur sera signalée.

public static void CatchException()
{
   try
   {
    Console.WriteLine("开始");
    var task = Task.Run(() =>
    {
     //throw new Exception("抛异常"); 
    });
    //注掉下面这行代码,观察异常结果
    //task.Wait();
    task.Dispose();
    Console.WriteLine("结束");
   }
   catch(Exception ex)
   {
    Console.WriteLine(ex.Message);
   }
}
Copier après la connexion

7 Démonstration de blocage

Supposons tsak1 et task2 si le premier verrou est obtenu avec succès avant l'obtention du deuxième verrou (pour tsak1, le deuxième verrou demandé est LockedObj2, et pour la tâche2, il s'agit de LockedObj1), un blocage se produira.

private static readonly Object LockedObj1 = new object();
private static readonly Object LockedObj2 = new object();
public static void LockShow()
{
   var task1 = Task.Run(() => 
   {
    lock (LockedObj1)
    {
     Console.WriteLine("get LockedObj1");
     lock (LockedObj2)
     {
      Console.WriteLine("get LockedObj2....");
     }
    }
   });
   var task2 = Task.Run(() =>
   {
    lock (LockedObj2)
    {
     Console.WriteLine("get LockedObj2");
     lock (LockedObj1)
     {
      Console.WriteLine("get LockedObj1....");
     }
    }
   });
}
Copier après la connexion

Plusieurs exécutions peuvent produire les deux résultats suivants : la première image est une situation dans laquelle une impasse ne se produit pas, et la deuxième image est lorsqu'une impasse se produit.

8 N'appelez pas la méthode Thread.Abort.

Task ne fournit pas la méthode Abort. Si vous utilisez le nouveau TPL (après .NET 4.0), vous ne penserez pas à ce problème. CancellationToken est généralement utilisé pour contrôler l'annulation des tâches.

9 Assurez-vous que les variables partagées sont sûres

Exécutez à plusieurs reprises, vous pouvez observer différents résultats, comme le montre la figure ci-dessous.

public static void Func()
{
   string s = "ASDFGH";
   Parallel.Invoke(
    () => { s = s.Replace("A", "1"); s = s.Replace("S", "1s"); }, 
    () => { s = s.Replace("A", "2"); s = s.Replace("S", "2s"); }, 
    () => { s = s.Replace("A", "3"); });
   Console.WriteLine(s);
}
Copier après la connexion

10 surabonnement et sous-application du processeur

public static void Func()
{
   ParallelOptions po = new ParallelOptions();
   //超额申请,处理器只有4个逻辑内核,结果设置并行度为10且是个逻辑内核均在工作,等待的任务数量大于0.
   po.MaxDegreeOfParallelism = 10;
   //申请不足,处理器有4个逻辑内核,却指定并行度为3,还有一个空闲的内核没有被占用(也有可能被其他线程占用,这里假设在指定并行度为3的情况下,另一个内核空闲)
   po.MaxDegreeOfParallelism = 3;
   List<int> list = new List<int>();
   Parallel.ForEach(list, po, m =>
   {
    //业务
   });
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!