Tom*_*Tom 4 .net c# mono multithreading backgroundworker
我有Mono的困境.我试图了解BackgroundWorker实例不会同时运行的方式或原因,或者至少不能非常有效或快速地运行实例.这几乎就像线程的数量受到限制一样,但我不是Mono开发人员或.NET开发人员,所以我把自己置于我的兄弟们的怜悯之下.
请考虑以下示例:
using System;
using System.ComponentModel;
using System.Threading;
namespace backgroundworkertest
{
class MainClass
{
public static void foo(object sender, DoWorkEventArgs e) {
Console.WriteLine("Start");
Thread.Sleep(500);
Console.WriteLine("Done");
}
public static void Main (string[] args)
{
for(int i = 0; i < 6; i++) {
BackgroundWorker b = new BackgroundWorker();
b.WorkerReportsProgress = false;
b.DoWork += new DoWorkEventHandler(foo);
b.RunWorkerAsync();
}
Thread.Sleep(2000);
Console.WriteLine("Really done");
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行上面的内容时,我得到以下输出.
Start Start Done Start Start Done Start Done Really Done
首先,并非所有的BackgroundWorkers都在两秒内完成.从循环中可以清楚地看出我正在实例化6名工人,但只有3名人员打印"完成".如果所有6个人同时运行,我觉得两秒钟应该足够让这些工人完成.
真正的内幕故事是我有一个运行良好的应用程序(使用大量的BackgroundWorkers在后台通过HTTP获取图像.但不同的是,这个应用程序是在C#.NET中实现的.当我移植应用程序时对于Mono,BackgroundWorkers似乎一次只能运行一对,并且HTTP连接很容易超时.我想看看是否是这种情况,因此上面的示例和问题......
这里发生了什么?为什么并非所有的BackgroundWorkers同时运行?我需要设置一些参数吗?
我对Mono的实现并不是100%肯定,但我对微软的版本相当了解,我只能假设Mono的行为方式相同或类似.
首先,澄清一下,事实上,BackgroundWorker 它确实产生了.NET线程(与本机线程不同),它与你ThreadPool.QueueUserWorkItem自己调用一样.这是一个微小的细节,可以帮助您理解为什么您会看到这种行为.重要的是要记住.NET中的线程可能实际上并不代表本机线程.实际上,所有6个后台工作程序在运行6个.NET线程时都可以在1-2个本机线程上运行.在我的机器上,实际上只有3个本机线程使用上面的代码生成.
其次,您没有考虑构造new BackgroundWorker,设置委托,然后异步运行worker所花费的时间,这可能涉及也可能不涉及创建本机线程,这实际上是一项相当昂贵的操作.添加一个计时器,在我的测试中,总共需要一点点的时间来创建所有六个,有时候更长一点.由于调度,ThreadPool可能需要几毫秒才能发现所有线程都饱和/阻塞(因为Thread.Sleep),然后创建一个新线程.这意味着,在某些情况下,您的后台工作人员可能会在0:01:700左右开始,只剩下300毫秒,但该功能会休眠500毫秒.没有足够的时间完成任务.
我不认为Mono的实现运行速度比微软慢一点是有争议的,我确信你可能没有发现你可以在运行时发现同样的行为.
如果有疑问,请责怪自己的代码,因为这通常是问题所在.睡觉你期望手术完成的时间,并不是一个真正的测试方法.如果计算机上运行其他程序会发生什么? Thread.Sleep如果其他进程的线程已抢占你的线程,则运行速度不会变慢.在这种情况下,情况会更糟.
如果您要在foo方法中将代码更改为睡眠5毫秒,并在创建后台工作程序后在main方法中等待20毫秒,则您等待的比率相同,并且我能够看到以下内容:
Start Start Done Done Start Start Really done Press any key to continue . . .
只有两个完成,甚至没有全部开始.我希望你现在看到测试中的缺陷.它们同时运行,我猜你的问题可能在其他地方.你说你在后台通过http获取图像.请记住,如果某些东西不能正常工作,我会说只有1%的时间实际上有一些时髦的运行时间,另外99%的时间是你的代码.您使用的是同步还是异步I/O?只有一个线程处理请求?我从那里开始.
编辑:
我决定看看Mono中的性能是什么样的,而不仅仅依赖于我在Microsoft实现中发现的内容.在发现Mono实际上正在开始所有6个背景作品之后; 它们都在2000ms的范围内完成!为了记录,这里是结果的比较.我稍微修改了代码以显示正在发生的事情,但我向你保证,当我按原样运行你的代码时,我得到了相同的结果.在主线程进入2000ms睡眠之前打印"完成创建..."消息,其中打印的时间戳是后台工作人员输入其工作方法的时刻.
Windows Mono Done Creating... Done Creating... 00:00:00.0018610 00:00:00.0088775 00:00:00.0019544 Start Start 00:00:00.5074494 Start Start Done Done Done 00:00:00.5615083 00:00:00.5027995 Start Start Done 00:00:00.5028008 00:00:01.0082133 Start Start Done 00:00:01.0082900 Done Start 00:00:01.0025428 Done Start 00:00:01.0618140 00:00:01.0026164 Start Start Done Done Done Done Done Really done Really done
我在完全相同的两个盒子上运行测试(戴尔T3400,相同的硬件),一个是Windows 7 x64,另一个是Ubuntu 12.04 x64.没有不同.确保您使用可执行文件的发布版本对此进行测试,而不附加任何调试程序.还要确保您在相同的硬件上进行测试.你的linux/mono安装问题是可能的,但不太可能,这是一个问题(假设你在linux上运行mono,而不是windows).就像我之前说过的那样,我认为这些结果支持它,我不认为这是问题所在.我会在你的代码中的某个地方寻找其他地方.
| 归档时间: |
|
| 查看次数: |
3081 次 |
| 最近记录: |