none
关于c#锁阻塞的问题 RRS feed

  • 问题

  • 你好,我要写个程序100ms内处理第三方dll返回的10000条数据,如果处理不完第三方dll就会抛出错误导致程序关闭。

    于是我分两个线程写,一个线程读取数据到queue,保证100ms中能够读光10000条数据,另外线程每隔一段时间处理这些数据并把结果保存到数据库。

    用queue时多线程需要加lock,否则会报错index out of range(网上查了,貌似ms的bug),但是加了锁之后却发现又不能再100ms内处理完这10000条数据了,于是第三方dll又报错,不知道我这种情况应该怎么处理比较好,麻烦的是100ms中必须把10000个数据加入到队列以便另外的线程处理,同时又不能加锁,如果加锁貌似就没有多线程的效果了。谢谢!

    2012年6月19日 14:39

答案

  • 是的,用lock的话恐怕无法达到此目的。你可以使用消息锁来完成此目的(另外不要开辟另外一个线程保存,直接子线程完成某个任务,直接保存)。

    此示例演示如何使用分段求和方式求出1~10000的和:

    public class Test
        {
            public static void Main()
            {
                int[] numbers = new int[10000];
                //分段求和结果存放
                int[] sums = new int[5];
    
                const int BLOCK = 2000;     //每个线程统计2000个数字和
    
                for (int i = 1; i <=10000; i++)
                {
                    numbers[i - 1] = i;
                }
    
                AutoResetEvent[] flags = new AutoResetEvent[5];
                for (int i = 0; i < 5; i++)
                {
                    int temp = i;
                    flags[temp] = new AutoResetEvent(false);   //初始化信号为空
                }
                
                //线程池,开辟5个线程
                for (int i = 0; i <5; ++i)
                {
                    int temp = i;
                    Thread th = new Thread(new ThreadStart(
                        delegate()
                        {
                            for (int j = temp * BLOCK; j < temp * BLOCK + BLOCK; ++j)
                            {
                                sums[temp] += numbers[j];
                            }
                            //此处直接写入数据库,因为当前线程已经完成任务了
                            Console.WriteLine("线程"+(i+1)+"已经完成任务,分布求和为:"+sums[i]);
                            flags[temp].Set();
                        }));
                    th.IsBackground = true;
                    th.Start();
                }
                WaitHandle.WaitAll(flags);
                Console.WriteLine(sums.Sum());
            }
        }

    【执行结果】


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年6月20日 3:41
    版主

全部回复

  • 是的,用lock的话恐怕无法达到此目的。你可以使用消息锁来完成此目的(另外不要开辟另外一个线程保存,直接子线程完成某个任务,直接保存)。

    此示例演示如何使用分段求和方式求出1~10000的和:

    public class Test
        {
            public static void Main()
            {
                int[] numbers = new int[10000];
                //分段求和结果存放
                int[] sums = new int[5];
    
                const int BLOCK = 2000;     //每个线程统计2000个数字和
    
                for (int i = 1; i <=10000; i++)
                {
                    numbers[i - 1] = i;
                }
    
                AutoResetEvent[] flags = new AutoResetEvent[5];
                for (int i = 0; i < 5; i++)
                {
                    int temp = i;
                    flags[temp] = new AutoResetEvent(false);   //初始化信号为空
                }
                
                //线程池,开辟5个线程
                for (int i = 0; i <5; ++i)
                {
                    int temp = i;
                    Thread th = new Thread(new ThreadStart(
                        delegate()
                        {
                            for (int j = temp * BLOCK; j < temp * BLOCK + BLOCK; ++j)
                            {
                                sums[temp] += numbers[j];
                            }
                            //此处直接写入数据库,因为当前线程已经完成任务了
                            Console.WriteLine("线程"+(i+1)+"已经完成任务,分布求和为:"+sums[i]);
                            flags[temp].Set();
                        }));
                    th.IsBackground = true;
                    th.Start();
                }
                WaitHandle.WaitAll(flags);
                Console.WriteLine(sums.Sum());
            }
        }

    【执行结果】


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年6月20日 3:41
    版主
  • 还是不明白如何用到我的地方

    2012年6月20日 10:41
  • 还是不明白如何用到我的地方


    我是控制台啊,你看懂思路之后把它放在“比如单击按钮”事件中啥的。

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年6月21日 1:48
    版主