目前正在做一个Winform的项目,开发环境vs2010.  
项目中需要同时开4个线程来进行不同的数据传输, 这4个线程执行时间各不相同, 当4个线程都执行完毕后,进入下一轮数据传输 (还是用4个线程 传输不同的下一轮数据)。 这个过程中,不能block GUI界面。我的想法用thread pool中4个线程, 用volatile int numberOfFinished 这个变量来检查每一轮4个线程是不是都结束了.  不知道有没有更好的方法。请大家给出意见。谢谢了先。

解决方案 »

  1.   

    委托异步
    IAsyncResult 来判断也可以  
    回调函数就更好了
      

  2.   

    using System;
    using System.Threading;namespace ConsoleApplication1
    {
        class Program
        {
            private static object asyncLock = new object();        public static Int32 _NumberOfFinished;
            public static Int32 NumberOfFinished 
            { 
                get 
                {
                    return _NumberOfFinished; 
                }            set
                { 
                    _NumberOfFinished = value;                if (_NumberOfFinished == 4)
                    {
                        Console.WriteLine("所有线程完成,两秒后自动继续");
                        System.Threading.Thread.Sleep(2000);
                        Start();
                    }
                }
            }        static void Main(string[] args)
            {
                Start();            Console.ReadLine();
            }        static void Start()
            {
                NumberOfFinished = 0;
                for (Byte i = 0; i < 4; i++)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), i);
                }
            }        static void Foo(Object obj)
            {
                Int32 z = Byte.Parse(obj.ToString());
                for (Int32 i = 0; i < 500; i++)
                {
                    Console.WriteLine(i);
                }            lock (asyncLock)
                {
                    NumberOfFinished++;
                }
            }
        }
    }垃圾方法
      

  3.   

    谢谢,我大体看了一下这个Barrier的用法,感觉可以解决我的问题,但是相关的资料太少,不是很确定。 hhddzz你本人用过这个东西来解决多线程间的同步问题么?
      

  4.   

    这四个线程每个线程都包含一个AutoResetEvent,比如evnt1,evnt2,evnt3,evnt4,然后线程结束时evnti.set()
    主线程(或监控线程)使用WaitHandle.WaitAll(evnt1到4的数组)来判断四个事件是不是都标志了Set,如果是,则进入下一轮(用autoresetevent会自动reset),否则主线程将等待直到四个事件全部set
      

  5.   

    ManualResetEvent allDone = new ManualResetEvent(false);
      

  6.   

    winform中不block ui界面,建议使用BackgroundWorker组件,线程相关操作微软已经帮你封装好了,你只需要在BackgroundWorker事件中处理你的业务逻辑就可以了
      

  7.   


    这个方法我也想过,但是要保证UI的响应,必须开另外一个控制线程,在控制线程中来处理四个线程。而且这四个线程还需要和UI主线程来通信。 我担心控制不好会更麻烦。 不知道大家意见如何?
      

  8.   

    stackoverflow上的解答,大家看看如何
    http://stackoverflow.com/questions/12811924/multithread-control-of-net-winform-app?answertab=votes#tab-top
      

  9.   

    一样的啊,用backgroundworker其实就是在thread外面多包装了一下,看似省事,其实却让你不能深入去体会多线程的理念,至于你说的同UI的交互,你用SynchronizationContext可以代替invoker,也方便很多
      

  10.   

    先开一个线程,处理数据轮次的循环,在循环里开这四个线程,处理各自的数据,四个线程都开始执行后,都用Join()等待执行完毕,然后进入下一轮。
      

  11.   

    DWORD WaitForMultipleObjects(
      DWORD nCount, 
      CONST HANDLE* lpHandles, 
      BOOL fWaitAll, 
      DWORD dwMilliseconds 
    );Dllimport这个function,这个是windows API绝对靠谱
      

  12.   

    学会:
    1、ManualResetEvent、AutoResetEvent
    2、Thread、ThreadStart
    3、Invoke, delegate可以灵活应付线程操作。
      

  13.   

    这个类很简单,msdn有不少资料。
    Barrier这个类型的文档里面有例子,另外线程同步的一个专题里面也有Barrier的例子。
      

  14.   


    http://www.google.com.hk/#hl=zh-CN&lr=lang_zh-CN%7Clang_zh-TW&newwindow=1&safe=strict&tbs=lr:lang_1zh-CN%7Clang_1zh-TW&spell=1&q=.net+waithandle+waitall&sa=X&ei=2NZ2UPbMNIWfiAePkIGIAQ&ved=0CC8QvwUoAA&bav=on.2,or.r_gc.r_pw.&fp=5aa343445015814f&biw=1378&bih=844
      

  15.   

    http://topic.csdn.net/u/20121003/09/6e45c464-4889-4adc-bca3-e20a49706641.html?seed=1358793287&r=79813217
      

  16.   

    你去搜一下WaitHandler.WaitAll()的用法就会了
    主线程中声明WaitHandle[] finishedEvts = new WaitHandle[4]; //new ManaulResetEvent(false)
    4个子操作中执行完后Set()
    主线程将子操作全部排入UserWorkQueue之后,
    调用WaitHandler.WaitAll(finishedEvts, 5000)阻塞5000ms,只有它们全部执行完时才会返回True
      

  17.   


    问题是:在主线程(UI线程)中使用join会阻塞界面响应。包括用WaitAll(),WaitForMultipleObjects API ,什么的也都是这个问题。 
      

  18.   


    如果在UI线程中Wait/Join/Sleep,会阻塞UI的响应。 如果在控制线程中创建四个子线程,和UI线程的交互(比如显示进度条信息)就会成问题。
      

  19.   

    四个线程是主线程(UI线程)开的,但如果在UI线程中控制同步(比如用wait/join/sleep),会阻塞UI的响应,这是不允许的。所以要在另外一个线程中来进行同步控制。 
    但这种方法感觉不好,不知道你有什么建议?谢谢了
      

  20.   


    这个会阻塞主线程UI,不可行。  目前主线程UI不允许任何形式的阻塞,问题难点在这里呀。
      

  21.   

    soaringbird,你好。 在调度线程里创建和同步四个传输的子线程有如下的问题:主线程UI要动态的显示各个传输线程的进度条。这要求每个传输的子线程要通过UI的TaskScheduler/SynchronizationContext来刷新UI线程。 在控制线程中创建和协调传输子线程就没法实现刷新UI线程。 不知道有没有更好的方法。
      

  22.   

    soaringbird,谢谢,我试试看,你是说用SynchronizationContext这中方式来update UI,是么?
      

  23.   

    .net中的线程控制感觉怎么比Windows本身还麻烦,已经习惯了用Win API来做。现在看.net中这么多方案,没有一个有足够的灵活性的。
      

  24.   

    JerryWJH,有关线程:
     1)数据的线程安全
     2)线程同步
     3)死锁
     因为主线程/UI操作通常是线程不安全的,所以,.net使用线程同步来解决。关于主线程/UI和子线程同步的例子很多,你搜索一下就找到了。
     #10楼,使用信号量,很好的解决了你需要4个线程同步,建议每个线程判断:WaitHandle.WaitAll(evnt1到4的数组).....。这样,不需要控制线程。
      
      

  25.   

    都不看windows api
    另开一线程调用waitformultipleobjects,具体去找MSDN,windows核心编程也行。
      

  26.   

    这个基本知识我早就知道了,我在这里是征集最佳方案。 用一个单独的线程来waitformultipleobjects的话, 传输线程等还要和 UI线程交互 。 这样有6个线程,控制起来很麻烦。
      

  27.   

    可以再启动一个总的控制线程,控制线程中使用4个线程的Join()函数。