2012-05-07 155 views
1

(I asked this question)之前將事件轉換爲異步/阻塞呼叫,但忘記提及一些限制。這適用於Silverlight 4和C#4的Windows Phone 7.1(芒果),缺少System.Threading.Tasksawait以及更多,我希望再次提出一個沒有像this這樣的第三方庫的原生解決方案。)在Windows Phone 7(C#)

我正在爲自己的應用打包庫。爲了獲得某個屬性,我需要等待一個事件,該事件很快就會發生。我試圖將其封裝成阻塞呼叫。

基本上,我想轉

void Prepare() 
{ 
    foo = new Foo(); 
    foo.Initialized += OnFooInit; 
    foo.Start(); 
} 
string Bar 
{ 
    return foo.Bar; // Only available after OnFooInit has been called. 
} 

進入這個

string GetBarWithWait() 
{ 
    foo = new Foo(); 
    foo.Initialized += OnFooInit; 
    foo.Start(); 
    // Wait for OnFooInit to be called and run, but don't know how 
    return foo.Bar; 
} 

這怎麼可能最好地完成?

+1

現在,您可以下載'Microsoft.Bcl.Async'爲Windows Phone 7 - 它允許異步和等待的使用,你會預計 – Brendan

回答

1

你可以做這樣的事情:

string GetBarWithWait() 
{ 
    foo = new Foo(); 

    using (var mutex = new ManualResetEvent(false)) 
    { 
     foo.Initialized += (sender, e) => 
     { 
      try 
      { 
       OnFooInit(sender, e); 
      } 
      finally 
      { 
       mutex.Set(); 
      } 
     } 

     foo.Start(); 

     mutex.WaitOne(); 
    } 

    return foo.Bar; 
} 

但你必須絕對肯定的是,富會不管發生什麼叫Initialized事件。否則,你會永遠阻止線程。如果富有着某種錯誤事件處理程序,訂閱它,以避免阻塞你的線程:

string GetBarWithWait() 
{ 
    foo = new Foo(); 

    using (var mutex = new ManualResetEvent(false)) 
    { 
     foo.Error += (sender, e) => 
     { 
      // Whatever you want to do when an error happens 
      // Then unblock the thread 
      mutex.Set(); 
     } 

     foo.Initialized += (sender, e) => 
     { 
      try 
      { 
       OnFooInit(sender, e); 
      } 
      finally 
      { 
       mutex.Set(); 
      } 
     } 

     foo.Start(); 

     mutex.WaitOne(); 
    } 

    return foo.Bar; 
} 
+0

謝謝!這很好用!在等待答覆之前,我會再等一等。 –

+0

有一點需要注意,ReSharper在'finally {mutex.Set();}中說:「訪問disposed closure」。 }'。它是錯的還是..? –

+2

當離開'使用'模塊時,互斥體被放置。因此,如果在離開GetBarWithWait方法後調用了Foo的'Initialized'事件,那麼它將拋出異常。如果你知道它不會發生,你可以放心地忽略這個警告。 –