• 多线程调用中的注意事项


    注意:

    1、不管是哪种多线程方法,在线程中访问共享资源的时候一定要用lock锁起来!不然会由于冲突产生各种奇奇怪怪的问题。

    2、委托(含拉姆达表达式)中调用的方法,其参数如果是变量,它的值取决于运行的那一刻内存里的值。如果希望在创建任务的时候值是固定的,必须用object参数state作为创建任务的状态,把值给进去。(也就是《编译原理》中的“编译时”和“运行时”的差别)

    3、而对于委托的begininvoke方法,里面的回调参数,是IAsyncResult类型。需要用它的“AsyncState”属性(object类型)获取传入的的内容(这一点跟代码提示的内容不一样)。

    如果不太理解,看例子:

    对于第一点

     1 public partial class Form1 : Form
     2     {
     3         public Form1()
     4         {
     5             InitializeComponent();
     6             pBar1.Maximum = 200;
     7             pBar1.Step = 1;
     8             CheckForIllegalCrossThreadCalls = false;
     9         }
    10 
    11         private void button1_Click(object sender, EventArgs e)
    12         {
    13             for (int i = 1; i <=100; i++)
    14             {
    15                 for (int j = 80; j <=81; j++)
    16                 {
    17                     ThreadPool.QueueUserWorkItem(tryconnect, new MyData(i, j));
    18                 }
    19             }
    20         }
    21         void tryconnect(object o)
    22         {
    23             int i, j;
    24             i = ((MyData)o).x;
    25             j = ((MyData)o).y;
    26             TcpClient tcp = new TcpClient();
    27             IAsyncResult async = tcp.BeginConnect(IPAddress.Parse($"192.168.1.{i}"), j, null, null);
    28             async.AsyncWaitHandle.WaitOne(1000);
    29             lock(listBox1)
    30             if (async.IsCompleted)
    31             {
    32                 listBox1.Items.Add($"192.168.1.{i}:{j} is open.");
    33             }
    34             else
    35             {
    36                 listBox1.Items.Add($"192.168.1.{i}:{j} is closed.");
    37             }
    38             //pBar1.PerformStep();
    39             tcp.Close();
    40             lock (pBar1)
    41             pBar1.PerformStep();
    42         }
    43 
    44         private void button2_Click(object sender, EventArgs e)
    45         {
    46             Close();
    47         }
    48     }
    49     class MyData
    50     {
    51         public int x, y;
    52         public MyData(int a,int b)
    53         {
    54             x = a;
    55             y = b;
    56         }
    57     }

    对于这种密集的异步线程,再调用异步tcp连接,如果没有第29行的lock,在vs下调试时关闭窗口的时候就有很大概率出现下图的错误:

     争夺资源越激烈概率越大,像代码中那样200次连接,已经是必然发生了。4次连接,大概25%左右发生概率。

    编译完成的应用直接打开,退出的时候会出现一个错误框,一闪而逝,不注意看不到。

    貌似不影响用户使用,但毕竟是隐患。

  • 相关阅读:
    Java初学者的学习路线推荐
    C#基础(七)虚函数
    C#基础(六)--枚举的一些常用操作
    C#基础(五)--枚举的含义及其应用
    C#基础(四)--值类型和引用类型,栈和堆的含义
    C#基础(三)--运算符及条件控制语句
    Zipkin+Sleuth调用链监控集成和使用
    jenkins集成cucumber-resport报告
    微信小程序自动化,记录趟过的坑!
    解压版mysql+免破解版Navicat,好用!
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/12766141.html
Copyright © 2020-2023  润新知