2010-02-12 24 views
11

Bazı eylemleri uyumsuz olarak gerçekleştiren ve bittiğinde bir olayı başlatan bir yönteme sahip olduğumuz bu ortak senaryoya sahibiz.Eşzamansız bir yöntemi senkronize etmenin genel bir yolu var mı?

ManualResetEvent reset = new ManualResetEvent(false); 
someobject.AsyncActionDone += (sender, args) => reset.Set(); 
someobject.PerformAsyncAction(); 
reset.WaitOne(); 

Bunu yapmak için bir yardımcı yöntem yazmanın bir yolu var mı:

biz eşzamanlı yerine biz şuna benzer kodu var yapmadıysanız istediğiniz zamanlar vardır? İşlemi gerçekleştirmek için iletebilirim, ancak bir EventHandler parametresini parametre olarak geçirebildiğiniz gibi görünmediğinden yardımcı yöntemin hangi olayı dinleyeceğini bilmesini sağlayan bir şeyden nasıl geçeceğimi bilmiyorum.

Tercihen yansıma gerektirmeyen bir çözüm

bazı karışıklıklara gibi görünüyor

, bu nedir SomeObject sınıfının bir örneğidir gibidir: ben senin kayması yakalamak ise

public class SomeClass 
{ 
    private ExternalServer someServerOverTheNetwork = new ExternalServer(); 

    public event EventHandler AsyncActionDone; 
    public Data SomeData { get; set; } 
    public void PerformAsyncAction() 
    { 
     someServerOverTheNetwork.GetSomeData(OnDataRetrived); 
    } 

    public Data OnDataRetrived(Data someData) 
    { 
     AsyncActionDone(this, new DataEventArgs(someData)); 
    } 
} 
+0

Biri nesnesinin uygulayıcısı mısınız, yoksa değiştirilemeyen bir kitaplık türü mü? –

+0

Ancak, böyle birçok nesne var. Eylemlerin çoğu, bir sunucuya istek göndermeyi ve sonucun geri gelmesini beklemeyi içerir, dolayısıyla varsayılan olarak neden uyumsuzlar. – Davy8

+0

En yaygın eylemlerimizden biri için bunu sunucudan nesnelerin bir listesini önbelleğe almanın bir yöntemine sahibiz, ancak tam olarak nesne tipini ve dinlenecek olayı bilmemize bağlıdır. Hangi olayı dinleyebilmek isterim ki çift kodları azaltabiliriz, çünkü farklı olan tek şey metot ve tamamlandıktan sonra ortaya çıkan olaydır. – Davy8

cevap

4

Asenkron çalışma yapan nesnelere Asynchronous Design Pattern uygulanmasını düşünürüm.

public object Operation(object arg) 
{ 
    var ar = BeginOperation(arg, null, null); 

    return EndOperation(ar); 
} 

public IAsyncResult BeginOperation(object arg, AsyncCallback asyncCallback, object state) 
{ 
    AsyncResult asyncResult = new AsyncResult(asyncCallback, state); 

    // Lauch the asynchronous operation 

    return asyncResult; 
} 

private void LaunchOperation(AsyncResult asyncResult) 
{ 
    // Do something asynchronously and call OnOperationFinished when finished 
} 

private void OnOperationFinished(AsyncResult asyncResult, object result) 
{ 
    asyncResult.Complete(result); 
} 


public object EndOperation(IAsyncResult asyncResult) 
{ 
    AsyncResult ar = (AsyncResult)asyncResult; 

    return ar.EndInvoke(); 
} 

Bu modelde, nesnenizde eşzamanlı eşzamansız birden çok işlem yapma esnekliğine sahipsiniz.

Not: Genel bir AsyncResult sınıfının web'deki uygulamasını kolayca bulabilirsiniz.

Düzenleme:

tüm nesne yalnızca bir asenkron operasyon olabilir eğer güncel tasarım tutmak istiyorum gibi, o zaman bir IAsyncOperation arayüzünü tanımlamak ve tüm nesnesinde uygulamak olabilir. Nesnelerinizin birden asenkron operasyon içerebilir sonra yansıma olmadan seni ne yapmak istediğinizi elde etmek için bir yol olduğunu düşünüyorum,

public static CallSynchronously(IAsyncOperation asyncOperation) 
{ 
    ManualResetEvent reset = new ManualResetEvent(false); 
    asyncOperation.AsyncActionDone += (sender, args) => reset.Set(); 
    asyncOperation.PerformAsyncAction(); 
    reset.WaitOne(); 
} 

, ama yine de tanımlayabiliriz:

public interface IAsyncOperation 
{ 
    event EventHandler AsyncActionDone; 
    void PerformAsyncAction(); 
} 

Sonra olabilir ManualResetEvent öğesini saran tüm senkronize olmayan işlemlerin senkronize bir sürümü.

public void PerformAction() 
{ 
    ManualResetEvent reset = new ManualResetEvent(false); 
    this.AsyncActionDone += (sender, args) => reset.Set(); 
    this.PerformAsyncAction(); 
    reset.WaitOne(); 
} 
+0

"someobject" sınıfını değiştirmeyi içermeyen bir çözüm için çekim yapıyorum Mevcut model, sistemimizde zaten düzinelerce sınıfta mevcut. – Davy8

+0

Umarız daha iyi bir açıklama ile düzenlenmiş soru – Davy8

+0

Yanıtı da düzenlediniz. –

3

yapabilirsiniz basitçe şu şekilde delegeleri kullanmak aramayı işlev için, temsilci yaratma,

public delegate string AsyncDelegate(); 

sonra diyoruz bir proxy işlev yardımıyla oluşturmanızı sağlar Böyle iyon:

public static void ExecuteSync(AsyncDelegate func) 
    { 
     ManualResetEvent reset = new ManualResetEvent(false); 
     int threadId; 
     func.BeginInvoke((a)=>reset.Set(), null); 
     reset.WaitOne(); 
    } 

İşte tüm, böyle tamamlanması veya bir şeyden sonra çalıştırmak için başka fonksiyon temsilciyi ekleyerek biraz daha karmaşık hale getirebilir ..

tadını çıkarın!

+0

Eğer zaten eşzamanlı bir fonksiyonunuz olduğunu varsayarsam yanlış olmazsa, öyle değil mi? 'Someobject.PerformAsyncAction();' i çağırdığımda, eylemi sıraya alır ve hemen geri döner, işlevimi gerçekten gerçekleştirildiğinde bildiğim yönteminize geçirdiğim işlevi görmüyorum. – Davy8

+0

Eylem tamamlandığında, ManualResetEvent öğesini "ayarlayan" geri çağrıyı çağırır. Ana işlev, ManualResetEvent öğesi "ayarlanmış" olana kadar geri dönmez. – Foole

+0

Eylem tamamlandığında nasıl anlar? Tüm Eylem işlevi bir mesaj gönderir ve hemen döner. – Davy8

İlgili konular