采用代理处理线程,在主线程中调用begininvoke启动N个线程,接着让主线程处于阻塞状态,等待任一线程结束后处理线程返回的值。如何实现这种方法?C++中采用WSAWaitForMultipleEvents函数。但是C#中如何处理我就不知道了。请各位指教,谢谢!

解决方案 »

  1.   

    http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconasynchronousdelegatesprogrammingsample.asp这里是等待某一个异步委托调用结束,等待任意一个结束是:
    ar.AsyncWaitHandle.WaitAny
      

  2.   

    谢谢楼上回复,我试了一下。发现如果用WaitAny等待10个WaitHandle数组,当一个有信号时,WaitAny返回所在的索引号,当下次再调用WaitAny时,刚才有信号的那个WaitHandle又被返回了。如果把返回的那个WaitHandle变成无信号状态?我没找到。我用另一种方法处理了这个问题。将返回有信号的那个WaitHandle从数组中删除,再调用WaitAny。但是这种方法很麻烦,以下是我的代码:public delegate int DelgFunc(int i);static int ThreadFunction(int i)
    {
    Thread.Sleep(i);
    return i;
    }static void Main() 
    {
    DelgFunc fc = new DelgFunc(ThreadFunction);
    int threads=10;
    ArrayList isr = new ArrayList();
    ArrayList wh= new ArrayList();
    for(int i=0;i<threads;i++)
    {
    Random rdm = new Random(i);
    IAsyncResult ias=fc.BeginInvoke(rdm.Next(2000,5000),null,null);
    isr.Add( ias );
    wh.Add( ias.AsyncWaitHandle );
    }
    for(int i=0;i<threads;i++)
    {
    WaitHandle[] wharry = (WaitHandle[]) wh.ToArray(typeof(WaitHandle));
    int nh=WaitHandle.WaitAny(wharry);
    Console.WriteLine(fc.EndInvoke((IAsyncResult)isr[nh]));
    isr.RemoveAt(nh);
    wh.RemoveAt(nh);
    }
    Console.ReadLine();
    }
    这样处理很麻烦的,有没有比较省事的方法?谢谢。
      

  3.   

    在BeginInvoke的第二个参数callback,其实是个委托,这个委托就是为了在一个异步委托调用完后让主线程处理这个异步委托的结果。
      

  4.   

    private static DelgFunc fc ;
    static int ThreadFunction(int i)
    {
    Thread.Sleep(i);
    return i;
    }
    /// <summary>
    /// The main entry point for the application.
    /// </summary>

    static void Main(string[] args)
    {
       
    fc = new DelgFunc(ThreadFunction);
    int threads=10;
    ArrayList isr = new ArrayList();
    ArrayList wh= new ArrayList();
    for(int i=0;i<threads;i++)
    {
    Random rdm = new Random(i);
    IAsyncResult ias=fc.BeginInvoke(rdm.Next(2000,5000),new System.AsyncCallback(ThreadResult),null);
    isr.Add( ias );
    wh.Add( ias.AsyncWaitHandle );
    }
    WaitHandle[] wharry = (WaitHandle[]) wh.ToArray(typeof(WaitHandle));

    Console.ReadLine(); }
    protected static  void ThreadResult(IAsyncResult ar)
    {
    if(ar.IsCompleted)
    {
      

    int ddd = (int) fc.EndInvoke(ar);
    Console.WriteLine(ddd);

         }
    }
      

  5.   

    WaitHandle[] wharry = (WaitHandle[]) wh.ToArray(typeof(WaitHandle));

    Console.ReadLine();
    中间少了一句话:
    WaitHandle.WaitAll(wharry);这样主线程在所有线程没有结束前阻塞了,而且每个线程处理完后通过ThreadResult代理来处理结果。
      

  6.   

    Thread中有一个Join()函数,利用此函数可以实现你的要求,非常简单,具体使用方法看MSDN中有详细的例子。
      

  7.   

    非常感谢 编程亮子 的热情回复.可能我讲的不太清楚.我的要求是在主线程中(本例为Main)最多启动N(比如5)个线程.但是现在有M(M>N,比如M=100)个线程要执行,如果同时启动M(100)个线程则系统开销则非常的大.且每个执行线程处理完后要返回处理后的结果,所以必须调用BeginInvoke方法启动线程.最后用EndInvoke来得到返回值.如果有任一线程结束则再开启一个剩下等待的线程去执行.所以这些方法必须都是主线程中(本例为Main)中完成,调用异步委托的回调函数无法满足我的要求.例如代码如下执行:do
    {
    调用BeginInvoke启动最多5个线程调用WaitHandle.WaitAny等待上述任一个线程结束}while(100个线程未全部执行完毕)为了实现上面的要求,如何优化代码?另:To ThreadSharp(ThreadSharp V2006)  我必须要使用BeginInvoke来启动线程,所以Thread无法满足我的要求.另外Join方法无法等待多个线程中的任一线程结束(处于有信号状态)这一点.
      

  8.   

    你这是线程池的应用萨。
    用。NET自带的ThreadPool
    或者
    http://www.codeproject.com/csharp/smartthreadpool.aspSmart Thread Pool这个池,里面有很多好的功能,比自带的那个强大多了如果你是研究线程的话,把它的源代码看懂。应该会有收获的。
      

  9.   

    再说BeginInvoke这个委托异步调用最终的结果是在NET的线程池里做的。也就是说你即使同时创建100000000000000BeginInvoke来启动线程,也不过是在NET默认的线程池里排队等候的!!!!
      

  10.   

    太谢谢你了,下个Smart Thread Pool研究研究.十分感谢.