2012-05-07 154 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'事件,那么它将抛出异常。如果你知道它不会发生,你可以放心地忽略这个警告。 –