zoukankan      html  css  js  c++  java
  • 多线程调用中的注意事项

    注意:

    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%左右发生概率。

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

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

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/12766141.html
Copyright © 2011-2022 走看看