线程会半路中间去执行别的代码吗

那该多好啊!!! 2018-10-19 02:56:06
最近在调试一个带有线程池程序时..单步调试时按F11时,发现程序一会跳到子线程里一会又从子线程里跳到主线程,所以我很疑惑。
1,如果在执行一个线程时,会不会还没有执行完这个线程又跳到主线程里去了,如果这样,那又是什么时候跑到这个线程里继续 执行下面的程序呢?

2,在主程序时实例化一个线程,并start()线程,可是我发现并没有及时跳到线程里工作,而是继续 主线程,然后在别的地方又忽然到子线程,为什么 在主线程里start()后并不会马上执行子线程,?

3,一般在读取CSV文档时,建立参数存储表,用arraylist好还是用Datetable呢
...全文
1481 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
望晓天 2018-10-23
  • 打赏
  • 举报
回复
线程调度。中断操作,很正常吧
number1killer 2018-10-22
  • 打赏
  • 举报
回复
在没有做线程同步的情况下,同一个进程中的线程是安装CPU时间片的分配来随机执行的,无法人为干涉。此外由于进程中的线程都是资源共享的,所以对这种程序进行调试的时候设置断点很讲究,必须不能破坏资源共享。
mk_lucifer 2018-10-21
  • 打赏
  • 举报
回复
程序跑飞的情况下会。。。
threenewbee 2018-10-20
  • 打赏
  • 举报
回复
操作系统会维护一个叫做线程上下文的东西,说白了就是当前的堆栈指针和所有cpu寄存器的值。
有了这个东西,就可以让一个线程暂停,然后把寄存器和堆栈保存起来,再将寄存器和堆栈设置为另一个线程之前保存的值。
此时cpu执行,就仿佛好像这个线程从来没有中断过一样。

打一个比方。把你速冻起来,保存个1000年,然后把你解冻,你又活过来了,你不会感觉到时间过了1000年,而是感觉突然整个世界前进了1000年,而你的意识是连续的。再比如,如果把你的记忆换成另一个人的,你不会感觉到你的记忆被换过,而是直接成为另一个人了。
  • 打赏
  • 举报
回复
编程上先顺序执行(例如 PLINQ 和 LINQ 的区别只是一个 AsParallel 后缀函数调用的区别,非常容易在并发和顺序之间随时切换),对于调试不了的代码就不要进入调试。 如果可能你还是要写测试,以自动测试驱动开发,而不是以手动模拟用户操作来驱动开发。
  • 打赏
  • 举报
回复
线程运行的任务中的业务设计,要保证尽量不要有共享内容需要读写。并且任务之间采用通用的消息通讯/委托回调方式。这样可以减少冲突调试复杂性。 对于你来说,一方面减少多线程使用,接下来使用 System.Diagnostics.DebuggerStepThrough 等标签来声明具体任务方法让调试器不要进入底层方法中,因为这些方法你调试不起,它会显示得很混乱,你只能当作“黑箱”去看看它的外边的输入输出就够了。
  • 打赏
  • 举报
回复
那就结合你的情况简单来说我的建议吧: 多线程并发程序不可能用调试驱动开发。你可能需要改为顺序执行方式,先用你的手动模拟“点点点”加上断点调试方式里搞开发,然后尽可能使用成熟的、简单易懂的并发框架和方法,例如使用 PLINQ方式,避免使用奇技淫巧。一旦有调试需求,你需要迅速改回单线程顺序操作的代码,牺牲所谓的性能合并发行,来保证你还能调试开发。这样才能适合自己。
  • 打赏
  • 举报
回复
非常感谢,原来调试的时候不能设置太多断点,
  • 打赏
  • 举报
回复
引用 11 楼 sp1234 的回复:
你随便找一个大点的流行的开源软件看看,里边通常都有测试程序。大部分优秀软件的测试程序的代码量相当于软件本身、甚至超出。

如果你看到一个程序员整天“写程序”但是没有自动测试代码,然后他按 F5 运行程序然后手工模拟用户的几个操作来“点点点鼠标”来进行所谓的“调试”,这就是业余爱好者的编程方式,离专业开发者起码还差一个“测试驱动开发”的知识层次。那么你可以看到,工程、质量、过程通常是不同的。

谢谢,原来测试这么复杂,没有搞过互联网,我只能在底下仰望。。我们做的一般是上位机程序,和自动设备运动控制打交道的那种。不需要写那么复杂。老板最多给二三个月就要交任务的。
比如某个机器项目开自动运行时,有几个工位分别开几个线程然后执行,但是执行时有顺序的要求,调试的时候想知道一些变量的执行顺序。
对于线程里的程序跳来跳去的,有时候 我还以为是我的代码写错了,万一跑错了,机器就要撞机了,
所以调试线程的时候有什么好方法吗?



  • 打赏
  • 举报
回复
你随便找一个大点的流行的开源软件看看,里边通常都有测试程序。大部分优秀软件的测试程序的代码量相当于软件本身、甚至超出。 如果你看到一个程序员整天“写程序”但是没有自动测试代码,然后他按 F5 运行程序然后手工模拟用户的几个操作来“点点点鼠标”来进行所谓的“调试”,这就是业余爱好者的编程方式,离专业开发者起码还差一个“测试驱动开发”的知识层次。那么你可以看到,工程、质量、过程通常是不同的。
  • 打赏
  • 举报
回复
引用 7 楼 z15920696563 的回复:
请问一下如果在执行一个子线程时,难道不执行完这个线程,在去执行别的子线程或主线程吗? 那如果去执行别的线程又如何能跳回来执行完这个子线程呢
多线程并发操作,自然是“没法调试”的。你还来手动调试这就比较荒唐啦。 开发以测试驱动,而不是手动“点点点”。比如说每过半个小时,你可能都运行起测试程序,让几百个测试用例顺序执行1遍,再几百个线程并发执行10遍,然后看测试是否完毕。测试驱动开发,基本上很少调试,因为一看到 vs 捕获到的 bug 并且从调试器上看一下堆栈内各层入口的变量值,就知道改什么地方了。即使是手动需要 F10 或者 F11 执行几步,也是在第一遍顺序测试时让 vs 捕获 bug 时在调试器上调试,而并发测试中捕获 bug 之后也是只能看静态堆栈内容而不能手动执行什么步骤的。 任何代码改动,以前的测试结果都要归零,都要“回归测试”。所以通常为了快速测试最近的改动,可能首先选择最近3天的测试用例先进行测试。而不是整个系统的测试用例。 比如说我们中午吃饭时运行测试程序,让它自动测试着,然后1小时之后回来看结果,可以看到200个测试用例运行了5000次测试,100%通过。这样时候我们才能开始写下面一个功能的十几行、几十行代码,写好了再来测试。 我再强调一遍,不知道你是否有这个理解里:专业开发是测试驱动,而测试是先进行顺序测试,然后才进行并发多线程测试。并不是手动随便“点点点”鼠标那种方式。要搞懂测试跟调试的区别!对于复杂一点的程序,特别是并发、异步机制的程序,如果你不能理解这个区别那么所有的做法也都不能真正理解。
  • 打赏
  • 举报
回复
引用 5 楼 lwqwag 的回复:
Java中的

List<T> list=new ArrayList<T>();
真是弱智一般
你写的这个是上世纪末的 java 语法吗?.net 最初是针对2000年的 java 的,跟现在的 java 没什么关系,现在的 java 最近10几年都在学 c#/.net。
  • 打赏
  • 举报
回复
提出这个问题所处的状态,是在开发时,需要按 F10、F11 进行步进调试,结果发现脑子根本不够用了,没法记住各个不同线程方法的跳转切换时的内部状态,调试开发方法彻底失败!
  • 打赏
  • 举报
回复
多线程并发运行,CPU自动会切换执行,无法人工干涉,一般为了让指定的线程先执行,可以设锁,上同步,任务代码锁上后,一个线程执行后其他线程无法在执行这个任务,这个线程也只有执行完这个任务才会去随机选择其他任务。我不太确定,你所提出这个问题是处于什么样的状态下,是在学习开发还是已经处于实际的开发工作中。最后一个问题,若是你现在只是在学习开发,一般老师或者你自学的话,Arraylist用的较多,还有其余的几个linklist、hashmap都会用到,实际开发中,一般都已有专人创建好的给你使用,团队也会讨论测试出哪种存储方式更合适。
圣殿骑士18 2018-10-20
  • 打赏
  • 举报
回复
线程本来就是并行的,哪有执行了这个就不执行那个,那不是不并行了吗?
一会儿调到线程1,一会儿跳到线程2,很正常,因为你加断点了!
你要调试某个线程,就只在这个线程加断点,不要在其他线程和主线程乱加断点。
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
windows 是抢占式调用线程的,每秒钟起码切换几十次线程上下文(如果你操作系统课程学的比较深,甚至可能是结合 windows 线程或者 unix 进程上下文数据结构来学的),你调试时自然是“跳越”的。

实际上,编程开发以测试为驱动,而测试时首先是顺序测试,其次才并发多线程测试。

开发不是你按 F5 启动程序然后用鼠标“点点点”各种画面的,这是业余开发玩儿程序。真正的开发是要自己写一个测试程序,来按照计划调用各种具体的方法,模拟各种 UI 层背后所调用的业务功能层操作。

所以你说的“调试”,大概就是跟初学者一样,按 F5 运行最终要发布的产品然后开始“点点点”吧。


请问一下如果在执行一个子线程时,难道不执行完这个线程,在去执行别的子线程或主线程吗?
那如果去执行别的线程又如何能跳回来执行完这个子线程呢
xuzuning 2018-10-19
  • 打赏
  • 举报
回复
1、你只有一颗 CPU,所以任何时刻都只能做一件事情(虽然你的 CPU 是多核的,但一般是不会去利用的,除非你使用了 Parallel 类 或 PLINQ)
所以说:一个线程是在其他线程的间隙中运行的,由操作系统调度,无法人工干预)
多个线程轮流运行,从而达到提高 CPU 利用率的目的(注意:不是提高程序运行效率)
2、前面已经说了,线程的执行与否,是操作系统调度的,不是你说 start() 就能 start 了的
3、arraylist 比 Datetable 的包容性强,但后续处理要复杂
被你绕了一下
Datetable 作为扩展工具,从 C 语言就开始能用了(那时还没有类的概念,还不能把一行数据当作一个整体来使用)
ArrayList 可以存放任何类型的对象(所以说包容性强),但取出时你需要鉴别得到的是什么,不能一概而论(所以说后续处理要复杂)
List<T> 自存放指定类型的数据,操作起来最简单

如果你是一个一个单元格单独读取的,那么自然应使用 DataTable
但你已经提到 ArrayList 了,显然你是按行读取到类实例中的,那么 ArrayList 和 List<T> 都可以,当然首选 List<T>

其实 List<T> 中 IList 类型的数据载体,就是 ArrayList。你去看看 List<T> 就知道了
lwqwag 2018-10-19
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
对于最后一个问题,类似 ArrayList 这类都是最古老的年代 .net 模仿 java 的产物,而 .net 自身又创建了强类型的更好的一套类型(例如 List 和 List<T>)。只不过因为那是“古老年代”,微软的 .net 需要坑 java 程序员一下,所以没有删除 java 垃圾类型。

现在的 .net core 等等,甚至都可能删除了 ArrayList 这类东西。而 .net framework 中的基本数据类型才是基础。


Java中的

List<T> list=new ArrayList<T>();

真是弱智一般
  • 打赏
  • 举报
回复
原始的 DataTable 也是弱类型的。比如说 List<Product>、比如说 Dictionary<string, User> 这些都是强类型的数据集合中的设计。
  • 打赏
  • 举报
回复
对于最后一个问题,类似 ArrayList 这类都是最古老的年代 .net 模仿 java 的产物,而 .net 自身又创建了强类型的更好的一套类型(例如 List 和 List<T>)。只不过因为那是“古老年代”,微软的 .net 需要坑 java 程序员一下,所以没有删除 java 垃圾类型。 现在的 .net core 等等,甚至都可能删除了 ArrayList 这类东西。而 .net framework 中的基本数据类型才是基础。
加载更多回复(2)

111,107

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧