2015-01-19 33 views
5

La mia applicazione utilizza .NET 4. Sto usando await asincrona utilizzando nuget packageUtilizzando attendono SemaphoreSlim.WaitAsync in .NET 4

Nella mia applicazione voglio fare un attendono sempahore chiamata WaitAsync come segue.

SemaphoreSlim semphore = new SemaphoreSlim(100); 
await semphore.WaitAsync(); 

Tuttavia sto ottenendo il seguente errore di compilazione.

'System.Threading.SemaphoreSlim' non contiene una definizione per 'WaitAsync' e nessun metodo di estensione 'WaitAsync' accettare un primo argomento di tipo 'System.Threading.SemaphoreSlim' stato trovato (sei manca un un riferimento all'assembly direttiva using o?)

Potrebbe esserci comunque di uisng WaitAsync in .NET 4.0?

risposta

5

Non è possibile utilizzare SemaphoreSlim.WaitAsync in .Net 4.0 poiché questo metodo è stato aggiunto a SemaphoreSlim in .Net 4.5.

È possibile comunque implementare il proprio AsyncSemaphore seguendo l'esempio di Stephen Toub in Building Async Coordination Primitives, Part 5: AsyncSemaphore:

public class AsyncSemaphore 
{ 
    private readonly static Task s_completed = Task.FromResult(true); 
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>(); 
    private int m_currentCount; 

    public AsyncSemaphore(int initialCount) 
    { 
     if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount"); 
     m_currentCount = initialCount; 
    } 

    public Task WaitAsync() 
    { 
     lock (m_waiters) 
     { 
      if (m_currentCount > 0) 
      { 
       --m_currentCount; 
       return s_completed; 
      } 
      else 
      { 
       var waiter = new TaskCompletionSource<bool>(); 
       m_waiters.Enqueue(waiter); 
       return waiter.Task; 
      } 
     } 
    } 
    public void Release() 
    { 
     TaskCompletionSource<bool> toRelease = null; 
     lock (m_waiters) 
     { 
      if (m_waiters.Count > 0) 
       toRelease = m_waiters.Dequeue(); 
      else 
       ++m_currentCount; 
     } 
     if (toRelease != null) 
      toRelease.SetResult(true); 
    } 
} 
1

No, è necessario eseguire l'aggiornamento a .NET 4.5 (o scrivere un'estensione WaitAsync (o un semaforo intrinsecamente asincrono)).

Le estensioni async per .NET 4.0 sono lì per consentire il supporto della parola chiave effettiva await. Gran parte del lavoro di .NET 4.5 sta aggiungendo operazioni asincrone a vari tipi di BCL che possono essere attesi. Se hai bisogno di queste operazioni, dovrai aggiornare la versione del framework che usi.

1

WaitAsync è stato introdotto con .Net 4.5. È necessario implementare te stesso come metodo di estensione esaminando source (non è sicuro se ciò è possibile) oppure è possibile utilizzare lo AsyncSemaphore di StephenToub.

1

Come il WaitAsync non è disponibile in .NET 4.0, è possibile utilizzare il codice Stephan Toub's series of async synchronization primitives:

public class AsyncSemaphore 
{ 
    private readonly static Task s_completed = Task.FromResult(true); 
    private readonly Queue<TaskCompletionSource<bool>> m_waiters = 
              new Queue<TaskCompletionSource<bool>>(); 
    private int m_currentCount; 

    public AsyncSemaphore(int initialCount) 
    { 
     if (initialCount < 0) 
     { 
      throw new ArgumentOutOfRangeException("initialCount"); 
     } 
     m_currentCount = initialCount; 
    } 

    public Task WaitAsync() 
    { 
     lock (m_waiters) 
     { 
      if (m_currentCount > 0) 
      { 
       --m_currentCount; 
       return s_completed; 
      } 
      else 
      { 
       var waiter = new TaskCompletionSource<bool>(); 
       m_waiters.Enqueue(waiter); 
       return waiter.Task; 
      } 
     } 
    } 

    public void Release() 
    { 
     TaskCompletionSource<bool> toRelease = null; 
     lock (m_waiters) 
     { 
      if (m_waiters.Count > 0) 
       toRelease = m_waiters.Dequeue(); 
      else 
       ++m_currentCount; 
     } 
     if (toRelease != null) 
      toRelease.SetResult(true); 
    } 
}