看看你的2是“另开多个线程处理队列信息”:如果你的队列,是用一个线程去“阻塞、然后顺序处理第一个任务”的,那么它只是顺序程序。而如果它是多线程并发处理任务,同样是多线程处理任务,那么你又凭什么认为方法1更复杂呢?因此你的方法2,纯粹是多余的。我只能认为你是因为比较容易抄袭到一些代码,所以会列出2。从你的流程描述中看不出有什么理由使用2。只要有1和3即可。使用3在“线程处理”问题方面跟2是一样的,因此这方面看它与1也是没法比的。但是使用MSMQ的好处就是这个服务可以自动进行消息持久化和通讯的独立服务,即使你的服务器进程意外中断,那么重启以后也可以继续执行。(当然,但愿你知道这些并且用到这些,否则根本没有使用3.)

解决方案 »

  1.   

    你是否理解“线程池”是个什么东东呢?系统线程池“就是一个队列”,你是否知道?如果你不直接使用系统线程池,先把消息“放到一个队列里”,然后用一个阻塞着的所谓“处理线程”再处理消息去并行进行“开多个线程处理队列信息”,你这样多此一举地额外多出一个队列并且额外多出一个阻塞式单线程(仅仅是为了作为“消费者线程线程分配工作”),有什么意义?这种东西,是10年前从java的一些国外教课书里抄袭来的“生产者-消费者”模式代码。但是那些作者并没有看过.net framework,它不知道人家.net framework已经有系统线程池了,告诉学生们“要自己开发一个拙略模拟消息线程池的队列”。一些人写.net框架应用的书,也抄袭人家的,根本不带自己的充分的分析判断。
      

  2.   

    方案1直接就是把消息处理过程“放入系统线程池”里自动管理的。而方案2写的“放入一个队列返回,然后另开多个线程处理队列信息”则是画蛇舔足,完全是在方案1的动作里边额外插入自定义的所谓队列、处理程序,只会增加了系统负担。除非你像 #3 楼那样把这个描述修改为”放入一个队列返回,然后用一个线程顺序处理队列信息“,这还能跟1区分出来需求不同。但是这显然就是性能最差的了。方案3注重的是独立的MSMQ的数据通讯安全方面的功能(不是指加密,是指不宜丢失)。但愿你不是人云亦云,而是能够看到技术的实际目的。
      

  3.   

    是我描述不清楚还是你理解有误?
    你的意思是接收数据后直接Task.factory.startnew(()=>DealData());更好?
    但是我说了数据接收有时频率很高,比如10毫秒就会接收数据。不断的执行Task.factory.startnew会不会造成性能问题?谢谢!昨天发完贴自己按照方式2写了代码。类似如下:
    public form1(){
    Task.factory.startnew(()=>DealData());
    }//接收数据
    void OndataReceive( string data){
    queue.Enqueue(data);放入队列 
    (如果是方式1,就是在这里直接Task.factory.startnew(()=>DealData());但是接收频率很快,也即可能1秒钟有几十次这个执行)retutn;
    }//处理数据
    void DealData(){
    while(true){
    for(int i =0; i < queue.Count; i++){
    string s= queue.Dequeue();
    ...处理数据....Thread.Sleep(10);
    }
    }.
    }
      

  4.   

    如果对要性能稳定的话,还是要配置MSMQ。
      

  5.   

    “如果是方式1,就是在这里直接Task.factory.startnew(()=>DealData());但是接收频率很快,也即可能1秒钟有几十次这个执行)
    ”为什么不在系统线程池里注册“...处理数据....”方法?你中间额外地弄一堆“什么队列、什么DealData、多出来的for循环,多出来这么多操作要进行,有什么意义?
      

  6.   


    不懂什么叫做“对性能稳定”。使用MSMQ肯定会让性能大大降低,以求稳定一点。实际上,通常是用不着这么稳定。如果服务器重启,那么未处理的消息可以扔掉。
      

  7.   

    都有很成熟的框架了这还自己写??比如有一个叫supersocket c++写的各种DL支持N个语言还有一个叫什么北峰之神的 都不错 里面都用socketasynceventargs写的你直接拿来用就是了..我虽然不是很懂代码 不过我看到你的 "异步" 里面居然还有while(true)我就笑了
      

  8.   


    你是意思是接收数据后使用ThreadPool.QueueUserWorkItem() ? 如果是这个,我看到的很多文章都推荐使用task来替代 ?
    另外,看到大家的回复我也不断在查阅资料,发现这个问题有点开放了。
    如http://blog.csdn.net/sq_zhuyi/article/details/6869661
      

  9.   

    期待指导中....我面临的问题主要就是数据高频接收,接收之后希望保证顺序处理数据。但不要影响阻塞接收。
    显示我自己根据前面的方式2设计了程序,即接收数据后直接放入队列【根据实际分为4个队列】,另外针对每一个队列开启一个线程专门处理队列中数据。但是这样线程这样多,是否影响性能...,怎样测试这种多线程程序性能?
    不知有没有可以参考的并行框架或好的处理方案。谢谢!!
    5个线程一点都不算多。只要不是100%CPU的线程,几十个都没问题。
      

  10.   

    首先我们来心平气和的讨论问题.
    void DealData(){
     while(true){
      }
    }
    我说了 我看到你这代码我就笑了..难道while(true)是你说的异步么.那beginreceive是什么???你连基本的东西好像都不是很清楚.还玩高端的东西..所谓的socket服务不就是开启一监听端口 接收来自世界各地的socket连接 接收数据么..而且核心方法难道不是3个  有连接,.,有发送...有断开.....这3个方法么?多少年前早就有人写好的东西了.我上面所有的意思都是 前人栽树后人乘凉而已..就好比aspnetpager都有人10年前就写出来的 我们拿来用就好啊.. 何必自己写.而且人家也开源,代码参考下就行了 这东西真没必要自己写的...
    10毫秒很高么...随便socket异步中的beginreceive就轻松搞定了..都不需要高端的socketasynceventargs..
      

  11.   


    10毫秒很高么...随便socket异步中的beginreceive就轻松搞定了..都不需要高端的socketasynceventargs..还是很感谢你的回复顶贴。
    你自己找本书看下吧,或者问问你身边的朋友,几千几万行代码你看到while(true)就是同步程序了,为什么不是直接死机奔溃了。死循环嘛
      

  12.   

    对于这种长时间运行的线程,必须要在每一个子循环中实现Sleep,一般来说Sleep(1)就可以,否则线程的数量会影响性能,如果是Windows桌面程序,主线程不需要Sleep,如果是Windows服务,主线程也需要Sleep.,使用Sleep的原因是释放CPU控制权,让其他线程得以有运行的机会。
      

  13.   

    如果你不需要顺序处理,可以再接受数据的函数里面,先调用异步接受新的数据,然后接着处理数据。
    如果需要顺序处理,就需要一个队列(频率高的最好是双队列),专门用一个线程来处理数据队列。可以用EventWaitHanlde做同步通知,也可以用Thread.Sleep(1)做轮询,都无所谓的。
      

  14.   

    你要顺序处理,就只能单线程,多线程根本没有任何意义
    即使自定义了队列,开了多线程之后,也无法保证执行的先后顺序,因为线程间各不干扰,有的执行快,有的执行慢,你没法保证先执行的就先完成.
    而如果使用线程同步,则效率降低,而且跟单线程等效,效率可能还不如单线程谢谢,是这样的,我根据我这边的具体数据分析,我这个接收到的数据可以分成4个类型,且这4个类型的数据可以互相独立。所以我现在的办法是,接收到数据后,判断数据类型,预先设置了4个队列,把数据分别放入相应的队列。然后,针对那4个队列,分别用4个线程去处理。处理方式就是前面的while(true ) ... 每次sleep(10)。我目前按照这个方式运行几天了,发现CPU 和 内存占用特别多(内存和CPU一直增)。我了解了下,据说是while(true)循环涉及了引用类型的全局变量字典【因为我处理数据完后会把结果保存在一个字典里,所以等于在while里使用了全局变量】,导致内存一直无法释放,所以会这样。不知有什么好的思路解决?
    谢谢!
      

  15.   


    谢谢,我现在就是用4个线程处理四个队列的数据。但是发现用Thread.Sleep(1)做轮询,期间我处理数据完后会把结果保存在一个字典里,所以等于在while里使用了全局变量,导致内存和CPU一直增....不知如何解决,谢谢!!
      

  16.   

    你要顺序处理,就只能单线程,多线程根本没有任何意义
    即使自定义了队列,开了多线程之后,也无法保证执行的先后顺序,因为线程间各不干扰,有的执行快,有的执行慢,你没法保证先执行的就先完成.
    而如果使用线程同步,则效率降低,而且跟单线程等效,效率可能还不如单线程谢谢,是这样的,我根据我这边的具体数据分析,我这个接收到的数据可以分成4个类型,且这4个类型的数据可以互相独立。所以我现在的办法是,接收到数据后,判断数据类型,预先设置了4个队列,把数据分别放入相应的队列。然后,针对那4个队列,分别用4个线程去处理。处理方式就是前面的while(true ) ... 每次sleep(10)。我目前按照这个方式运行几天了,发现CPU 和 内存占用特别多(内存和CPU一直增)。我了解了下,据说是while(true)循环涉及了引用类型的全局变量字典【因为我处理数据完后会把结果保存在一个字典里,所以等于在while里使用了全局变量】,导致内存一直无法释放,所以会这样。不知有什么好的思路解决?
    谢谢!个人感觉目前的问题是因为数据接收完后
    还要处理数据解析等操作,然后才通过队列实现了异步化。
    应该是接收数据后,触发数据处理事件,
    把耗时的数据拼包、数据校验及业务层解析等等统统放到线程池中去,
    数据解析完成后,这个任务就结束了。
    这种很频繁但执行时间比较断的数据处理模型特别适合用线程池。   memHandle = ThreadPool.RegisterWaitForSingleObject(
               dataEv,
               new WaitOrTimerCallback(RealDataHandler),
               this,
               10000,
               false
               );
      

  17.   

    你要顺序处理,就只能单线程,多线程根本没有任何意义
    即使自定义了队列,开了多线程之后,也无法保证执行的先后顺序,因为线程间各不干扰,有的执行快,有的执行慢,你没法保证先执行的就先完成.
    而如果使用线程同步,则效率降低,而且跟单线程等效,效率可能还不如单线程谢谢,是这样的,我根据我这边的具体数据分析,我这个接收到的数据可以分成4个类型,且这4个类型的数据可以互相独立。所以我现在的办法是,接收到数据后,判断数据类型,预先设置了4个队列,把数据分别放入相应的队列。然后,针对那4个队列,分别用4个线程去处理。处理方式就是前面的while(true ) ... 每次sleep(10)。我目前按照这个方式运行几天了,发现CPU 和 内存占用特别多(内存和CPU一直增)。我了解了下,据说是while(true)循环涉及了引用类型的全局变量字典【因为我处理数据完后会把结果保存在一个字典里,所以等于在while里使用了全局变量】,导致内存一直无法释放,所以会这样。不知有什么好的思路解决?
    谢谢!个人感觉目前的问题是因为数据接收完后
    还要处理数据解析等操作,然后才通过队列实现了异步化。
    应该是接收数据后,触发数据处理事件,
    把耗时的数据拼包、数据校验及业务层解析等等统统放到线程池中去,
    数据解析完成后,这个任务就结束了。
    这种很频繁但执行时间比较断的数据处理模型特别适合用线程池。   memHandle = ThreadPool.RegisterWaitForSingleObject(
               dataEv,
               new WaitOrTimerCallback(RealDataHandler),
               this,
               10000,
               false
               );谢谢!
    我参考了你的思路,现在改成接收到数据后,直接放入一个队列(因为要保证数据的顺序)。
    然后在form()构造函数里开启了一个处理线程。
    void start()
    {
    ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(ReadQueue), this, 10, false); 
    }
    这样让线程池每隔10ms就读一次队列。你看这样行不?或者是接收到数据后,直接
    ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(data(数据项)), this, 10, true); 
    ?谢谢!
      

  18.   

    你要顺序处理,就只能单线程,多线程根本没有任何意义
    即使自定义了队列,开了多线程之后,也无法保证执行的先后顺序,因为线程间各不干扰,有的执行快,有的执行慢,你没法保证先执行的就先完成.
    而如果使用线程同步,则效率降低,而且跟单线程等效,效率可能还不如单线程谢谢,是这样的,我根据我这边的具体数据分析,我这个接收到的数据可以分成4个类型,且这4个类型的数据可以互相独立。所以我现在的办法是,接收到数据后,判断数据类型,预先设置了4个队列,把数据分别放入相应的队列。然后,针对那4个队列,分别用4个线程去处理。处理方式就是前面的while(true ) ... 每次sleep(10)。我目前按照这个方式运行几天了,发现CPU 和 内存占用特别多(内存和CPU一直增)。我了解了下,据说是while(true)循环涉及了引用类型的全局变量字典【因为我处理数据完后会把结果保存在一个字典里,所以等于在while里使用了全局变量】,导致内存一直无法释放,所以会这样。不知有什么好的思路解决?
    谢谢!个人感觉目前的问题是因为数据接收完后
    还要处理数据解析等操作,然后才通过队列实现了异步化。
    应该是接收数据后,触发数据处理事件,
    把耗时的数据拼包、数据校验及业务层解析等等统统放到线程池中去,
    数据解析完成后,这个任务就结束了。
    这种很频繁但执行时间比较断的数据处理模型特别适合用线程池。   memHandle = ThreadPool.RegisterWaitForSingleObject(
               dataEv,
               new WaitOrTimerCallback(RealDataHandler),
               this,
               10000,
               false
               );谢谢!
    我参考了你的思路,现在改成接收到数据后,直接放入一个队列(因为要保证数据的顺序)。
    然后在form()构造函数里开启了一个处理线程。
    void start()
    {
    ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(ReadQueue), this, 10, false); 
    }
    这样让线程池每隔10ms就读一次队列。
    可行
    多说一句,多线程访问队列,须处理同步
    队列本身不是线程安全的,要加锁避免出脏数据
      

  19.   


    谢谢,我昨天调试发现同步问题了,加了lock控制。