2013-02-25 10 views
6

sahip olduğum her verilen bekleme kolları için beklemek zorunda hedefi vardır ancak belirli bir bekleme koldan iptal edilemez Aşağıdaki kod:C# WaitHandle iptal WaitAll

public static bool CancelableWaitAll(WaitHandle[] waitHandles, WaitHandle cancelWaitHandle) 
{ 
    var waitHandleList = new List<WaitHandle>(); 
    waitHandleList.Add(cancelWaitHandle); 
    waitHandleList.AddRange(waitHandles); 
    int handleIdx; 
    do 
    { 
     handleIdx = WaitHandle.WaitAny(waitHandleList.ToArray()); 
     waitHandleList.RemoveAt(handleIdx); 
    } 
    while (waitHandleList.Count > 1 && handleIdx != 0); 
    return handleIdx != 0; 
} 

Bu yalnızca ManualReset olaylar için çalışır. AutoReset olaylarını kullanırken WaitAny tüm sinyallenmiş olayları sıfırlar, ancak sadece ilk sinyalden döner (MSDN'ye göre).

Bu, AutoReset olayları ile, yoklama olmadan düzgün bir şekilde nasıl yapılır?

+0

Aşırı yüklenmiş yöntemlerden birini kullanmayı deneyin. Yapmaya başlamadan önce diziyi oluşturmaya çalışın, belki de yeni bilgiler edinebilirsiniz. –

+0

İptal olayı gündeme geldiğinde bunun nasıl olacağını anlayamıyorum? – LukeHennerley

+1

İptal olayı ortaya çıkarsa, verilen tüm waitHandles'ların beklemesi – Harry13

cevap

1

Yönteminizin doğru yazılmış şekilde çalışması gerektiğini düşünüyorum.

I WaitHandle.WaitAny() the Windows API function WaitForMultipleObjects() kullanır inanıyoruz dokümantasyonu için söyler:

modifikasyonu yalnızca, sinyal durum fonksiyonu geri neden nesne veya bir nesne için oluşur.

Doğruysa, kodunuzun çalışması gerektiği anlamına gelir.

Bir test programı yazdım. Bir AutoResetEvents yükü oluşturur ve CancelableWaitAll() öğesini çağırmadan önce bunların yarısını ayarlar. Ardından, AutoResetEvents öğesinin diğer yarısını ayarlamadan önce 5 saniye bekleyen bir iş parçacığı başlatır. Bu iş parçacığı başlatıldıktan hemen sonra, ana iş parçacığı CancelableWaitAll() işlevini çağırır.

WaitAny(), dizininde döndürülen dışındaki herhangi bir otomatik olay kümesini gerçekten sıfırlarsa, CancelableWaitAll() asla geri dönmez. geri dönmek Çünkü

(tabii 5 saniye sonra), senin kod AutoResetEvents ile çalışır iddia ediyorum: Maalesef

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

namespace Demo 
{ 
    public static class Program 
    { 
     private static void Main(string[] args) 
     { 
      AutoResetEvent[] events = new AutoResetEvent[32]; 

      for (int i = 0; i < events.Length; ++i) 
      { 
       events[i] = new AutoResetEvent(false); 
      } 

      // Set the first 16 auto reset events before calling CancelableWaitAll(). 

      for (int i = 0; i < 16; ++i) 
      { 
       events[i].Set(); 
      } 

      // Start a thread that waits five seconds and then sets the rest of the events. 

      Task.Factory.StartNew(() => setEvents(events)); 

      Console.WriteLine("Waiting for all events to be set."); 

      ManualResetEvent stopper = new ManualResetEvent(false); 
      CancelableWaitAll(events, stopper); 

      Console.WriteLine("Waited."); 
     } 

     private static void setEvents(AutoResetEvent[] events) 
     { 
      Thread.Sleep(5000); 

      for (int i = 16; i < events.Length; ++i) 
      { 
       events[i].Set(); 
      } 
     } 

     public static bool CancelableWaitAll(WaitHandle[] waitHandles, WaitHandle cancelWaitHandle) 
     { 
      var waitHandleList = new List<WaitHandle>(); 
      waitHandleList.Add(cancelWaitHandle); 
      waitHandleList.AddRange(waitHandles); 
      int handleIdx; 
      do 
      { 
       handleIdx = WaitHandle.WaitAny(waitHandleList.ToArray()); 
       waitHandleList.RemoveAt(handleIdx); 
      } 
      while (waitHandleList.Count > 1 && handleIdx != 0); 
      return handleIdx != 0; 
     } 
    } 
} 

, ben (WaitHandle.WaitAll() WaitForMultipleObjects kullandığı ispat edemez). Ancak, eğer yapmadıysa, WaitHandle.SafeWaitHandle'ı kullanarak OS olay tutamaçlarını kullanarak ve WaitForMultipleObjects() işlevini çağırmak için P/Invoke'u kullanarak kendiniz çağırabilirsiniz.