2011-06-10 14 views
6

Yalnızca eşzamansız işlevden geri arama geldiğinde çalıştırılması gereken bir işlev var.Eşzamansız işlev için geri arama alınana kadar iş parçacığı nasıl uyulur?

gibi ben asenkron fonksiyon Stop() ve kısa bir süre sonra ben asenkron fonksiyon Start() diyoruz diyoruz.

CallBack Durdurmadan Önce Sorun alındı ​​Start() çağrıldı ve bu nedenle sorun yaşıyorum.

public void SomeFunction() 
{ 

    Stop(); 
    //Do something; 

    Start(); 
} 

ama benim başlangıç ​​geri çağırmak Dur almadan önce() fonksiyonu: Bu .:

public void SomeFunction() 
{ 
    Stop(); 
} 

public void Stop_CallBack(eventargs e) 
{ 
    Start(); 
} 
ben bunu yapmak zorunda

yapamaz gibi Ayrıca iki fonksiyonların arama ayıramam böylece benim için sorunları yaratıyor.

Bu sorunu nasıl çözebilirim?

cevap

18

Bekleme tutamaçlarını kullanmak istediğiniz zaman budur. İşte bir yaklaşım göstermek için kısa bir kod örnektir: Zaten AutoResetEvent ve ManualRestEvent ile çalıştık

class AsyncDemo 
{ 
    AutoResetEvent stopWaitHandle = new AutoResetEvent(false); 
    public void SomeFunction() 
    {  
     Stop(); 
     stopWaitHandle.WaitOne(); // wait for callback  
     Start(); 
    } 
    private void Start() 
    { 
     // do something 
    } 
    private void Stop() 
    { 
     // This task simulates an asynchronous call that will invoke 
     // Stop_Callback upon completion. In real code you will probably 
     // have something like this instead: 
     // 
     //  someObject.DoSomethingAsync("input", Stop_Callback); 
     // 
     new Task(() => 
      { 
       Thread.Sleep(500); 
       Stop_Callback(); // invoke the callback 
      }).Start(); 
    } 

    private void Stop_Callback() 
    { 
     // signal the wait handle 
     stopWaitHandle.Set(); 
    } 

} 
+1

Neden 'Stop_Callback''e ihtiyacınız olduğunu açıklayabilir misiniz? Neden stopWaitHandle.Set(); 'doğrudan görevde değil? –

+1

@Daniel: * Ben * gerek yok; ancak soru, * "[...] işlevinin yalnızca bir geri çağrı alındığında çalıştırılması gereken [...]" * durumunu bildirir ve OP, belirtilen kod örneğinde böyle bir geri arama yapılmasını önermişti. OP kodunu mümkün olduğunca az yeniden yapılandırmayı tercih ediyorum. Geri arama, örneğin bekletme işlemine erişimi olmayan üçüncü taraf kodundan çağrılabilir. –

+0

Stop_callback'i arayamıyorum. Bu, başka bir uygulamadan aldığım geri arama. – Sumit

2

bu üye fonksiyonları gibi bakmak olduğundan, (bir olay üye değişkeni ekleyebilir ya bir ManualResetEvent veya AutoResetEvent. Sonra Stop() yönteminde sen Stop çağrılar arasında ise. Sinyallerini olay set() ve Başlat() Eğer olay için bekleyin

private AutoResetEvent _stopped = new AutoResetEvent(false); 

public void SomeFunction() 
{ 
    Stop(); 
    _stopped.WaitOne(); 
    Start(); 
} 

durdurma fonksiyonu size

private void Stop() 
{ 
    try 
    { 
     // Your code that does something to stop 
    } 
    finally 
    { 
     _stopped.Set(); // This signals the event 
    } 
} 

yapacağını bir ManualResetEvent kullanılıyorsa -.

private ManualResetEvent _stopped = new ManualResetEvent(false); 

public void SomeFunction() 
{ 
    Stop(); 
    _stopped.WaitOne(); 
    Start(); 
} 

private void Stop() 
{ 
    try 
    { 
     // Your code that does something to stop 
    } 
    finally 
    { 
     _stopped.Set(); // This signals the event 
    } 
} 

private void Start() 
{ 
    _stopped.Reset(); 

    // Your other start code here 
} 
+0

ve bunu sıfırlamak zorunda ardından ManualResetEvent kullanırsanız – Sumit

+0

çalıştı vermedi ('_stopped.Reset()') WaitOne çağrısından sonra, aksi takdirde sinyallenmiş bir durumda kalır. – pstrjds

+0

Otomatik ve El ile sıfırlama olaylarıyla çalışmadığından ne demek istiyorsunuz? Kodunuz WaitOne() çağrısında engellenmedi mi? Bu durumda daha fazla kod yazabilir misiniz? Durdur'u çağıran, bir şeyler yapıp Başlat'ı çağıran bir işleviniz varsa. Olay Duruşta sinyal verildiği ve sadece başlangıçta sıfırlandığı sürece, kodunuz olay bildirilene kadar WaitOne'da bloke olacaktır. – pstrjds

İlgili konular