首页 新闻 会员 周边 捐助

线程池将任务排队到队列后,竟丢失了该任务

0
悬赏园豆:15 [已解决问题] 解决于 2013-01-04 15:22

今天不小心发现一个问题一直不解。

      当我在一个方法中使用ThreadPool.QueueUserWorkItem插入任务时,如果方法执行过快会导致我插入的任务实际上没有执行。而若我插入任务后让线程等待一下,那么插入的任务就可以正常执行。。见代码

static void Main(string[] args)
{
    Example_RegisterWaitForSingleObject();

    Console.ReadKey();
}

private static void Example_RegisterWaitForSingleObject()
{
    ThreadPool.QueueUserWorkItem(o => { while (true) {     Thread.Sleep(500); Console.WriteLine("123"); } });
    Thread.Sleep(1000);
}

 

所以推断,将任务插入到线程池中是需要时间的,而若在这段时间中释放掉某些资源就会导致任务没有实际插入到队列中。

我的疑惑是:

1、到底我的推断整不正确。有没有更官方的解释,或则研究过win32的帮解释下

2、若实际代码中遇到这种情况大家都有什么好解决的办法(应该不会去Thread.Sleep()一下哇,最好有无阻塞式的方式)

问题补充:

有图有真相

滴答的雨的主页 滴答的雨 | 老鸟四级 | 园豆:3660
提问于:2013-01-03 21:46
< >
分享
最佳答案
0

我想问一句,你把你代码中的 Thread.Sleep 都去掉的话,Console.WriteLine("123"); 就不会执行了吗?

收获园豆:10
Launcher | 高人七级 |园豆:45050 | 2013-01-04 09:27

是啊,拿掉Sleep()就不会输出了。不知道是什么原因?而且是debug模式下的,也不存在编译器优化。

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 09:42

@滴答的雨: 下面的网友已经回答了你的问题。我不知道你是不是用的别的代码来测试的。

Launcher | 园豆:45050 (高人七级) | 2013-01-04 10:13

@Launcher: 我用的就是这段代码,不过我这边真没有输出……郁闷了……

我又测了下,(没有Sleep())我如果在QueueUserWorkItem下面再增加一个Console.Write就可以正常输出。或则我在调用完Example_RegisterWaitForSingleObject()方法在Mail()中做一个Console.Write也就可以正常输出了。。。

但如果我Main中只有Example_RegisterWaitForSingleObject()而Example_RegisterWaitForSingleObject()中只有QueueUserWorkItem就说明都不输出了。

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 10:43

@Launcher: 我的是VS2012

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 10:44

@滴答的雨: 看一下你的 QueueUserWorkItem 的返回值是什么。

Launcher | 园豆:45050 (高人七级) | 2013-01-04 10:57

@Launcher: 如果一断掉调试就会正常输出了。(只要有停顿或做了额外的输出就会插入到队列)

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 11:51

@滴答的雨: 根据你目前提供的材料,我是不是可以总结为现象是线程中的方法实际是执行了,只是你没在控制台看到输出,对吗?你可以先启动程序,让它运行10秒后,然后进入VS在代码:Console.WriteLine("123"); 处添加一个断点。

Launcher | 园豆:45050 (高人七级) | 2013-01-04 13:02

@Launcher: 可能是没办法看到输出吧!   只要我在console.readkey()前面在做些别的操作就会看到输出了

兄弟你那边是一直重现不出哇?真郁闷……帖子我再摆到下班看看

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 13:53

@滴答的雨: 那么我现在是不是可以肯定的认为你原文中的两个疑惑就没有了?因为并不存在插入线程池的线程没有运行的问题,只是没有看到Console.WriteLine("123")的显式结果而已。

请改成 Debug.WriteLine("123"),从你的调试窗口观测下。

另外你可以修改.Net Framework的版本为3.5,4.0,分别测试下。

Launcher | 园豆:45050 (高人七级) | 2013-01-04 14:22

@Launcher: 这个测试思路挺好的,哎,我入世未深啊……

我测试了

1、在4.0和4.5我这边还是不会输出的,但之前版本可以正常输出。

2、使用System.Diagnostics.Debug.Write("123");每个版本都可以输出

看来是由于虾米原因在控制台看不到输出吧!谢啦。

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 15:21

@滴答的雨: 其实啊,你可以把

while (true) { Console.WriteLine("123"); }

直接写到

Console.ReadKey();

之前,不用放入线程池中,看看有什么效果。

Launcher | 园豆:45050 (高人七级) | 2013-01-04 15:41
其他回答(1)
0

我按你的代码做了一下测试

private static void Example_RegisterWaitForSingleObject()
        {
            ThreadPool.QueueUserWorkItem(o => {
                while (true)
                {
                    //Thread.Sleep(500);
                    Console.WriteLine("123");
                }
            });
            //Thread.Sleep(1000);
        }

正常输出,没有任何问题

收获园豆:5
Rich.T | 园豆:3440 (老鸟四级) | 2013-01-04 10:06

奇怪了,我就是用的粘贴的代码试的,VS2012,没有输出……

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 10:43

@滴答的雨: 

我在2010中试的正常,没有下2012

支持(0) 反对(0) Rich.T | 园豆:3440 (老鸟四级) | 2013-01-04 10:45

@滴答的雨: 

你断点调试一下,看看是什么原因

支持(0) 反对(0) Rich.T | 园豆:3440 (老鸟四级) | 2013-01-04 10:54

@Rich.T: 断点的话就能正常输出了,好像是方法结束的太快,释放了某些资源?

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 11:47

@滴答的雨: 

我觉得是你电脑反映太慢

支持(0) 反对(0) Rich.T | 园豆:3440 (老鸟四级) | 2013-01-04 12:17

@Rich.T: ……不会啊,我在家笔记本I5+4g内存+独显和我在公司core2+2G+独显,效果一样

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-04 12:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册