2012-10-11 42 views
0

我与得到的数据为Silverlight 4应用挣扎。我的视图需要获取一些信息,所以它会调用我的DataProvider。我的DataProvider打电话给Oracle。这是一个需要回调的异步调用,所以我的DataProvider方法需要等待它。但是,如果我在异步调用之后在我的DataProvider方法中放置了Thread.Sleep循环,则回调从不会触发。如果我删除Thread.Sleep循环,回调命中,但到那时我的DataProvider方法已经完成,没有任何东西可以返回。如何最好地等待Silverlight 4的异步调用

的不同步性是没有价值的视图;它现在必须有这些数据继续前进。我很希望能够搞清楚的是我怎么能有DataProvider类做出响应从一个视图中的一个请求数的数据库调用,而不是返回,直到它准备好。在这种情况下,我并不介意这种观点没有反应;但我这样做的方式是完全锁定应用程序。

这是我有:

的观点,使这一呼吁:

m_Data = m_DataProvider.GetMyStuffData(some parameters to filter the data); 

DataProvider的识别参数,并开始建立起来的M_DATA对象。这需要大量的电话,其中一个看起来是这样的:

public override List<MyStuff> GetMyStuff(DateTime _startDay, DateTime _endDay) 
{ 
    var rc = new List<MyStuff>(); 
    m_WaitingForData = true; 
    var query = MyQueryString; 
    var parameters = new string[ ] { "My Parameter" }; 
    getOracleData(parameters, query, "My Query ID"); 
    while (m_WaitingForData) 
    { 
     Thread.Sleep(20); 
    } 
    // process Data which asynchronous call put into a member variable. 
    return rc; 
} 

getOracleData使异步调用,接线回调GetTable。

回调方法,GetTable,提取的数据转换成GetMyStuff期待一个成员变量,关闭m_WaitingForData,并退出。

回答

0

我结束了开发这个小类:

using System; 
using System.Linq; 
using System.Windows; 
using System.Collections.Generic; 

namespace MyNamespace 
{ 
    public class AsyncDataManager 
    { 
     // This dictionary will help handle waiting for asynchronous data callbacks. 
     private Dictionary<string, int[ ]> m_ExpectedData; 
     private Action m_FinalProcess; 
     private object m_Locker = new object(); 
    public AsyncDataManager(Action _finalProcess) 
    { 
     m_ExpectedData = new Dictionary<string, int[ ]>(); 
     m_FinalProcess = _finalProcess; 
    } 

    public void SetExpectation(string _key, int _occurrances = 1) 
    { 
     m_ExpectedData[ _key ] = new[ ] { _occurrances, 0 }; 
    } 

    public void ManageCallbacks(string _key, Action _action = null) 
    { 
     lock (m_Locker) 
     { 
      m_ExpectedData[ _key ][ 1 ]++; 
      if (_action != null) 
      { 
       _action(); 
      } 
      // Once all the expected callbacks have been handled, using a 
      // Dispatcher gets us back onto the UI thread and out of the scope of the lock. 
      if (!m_ExpectedData.Values.Any(v => v[ 0 ] != v[ 1 ])) 
      { 
       Deployment.Current.Dispatcher.BeginInvoke(m_FinalProcess); 
      } 
     } 
    } 

    // Without requiring that all expected async calls are complete, we can check for a certain set. 
    public bool TestForSubsetComplete(params string[ ] _items) 
    { 
     return (!m_ExpectedData.Keys.ToList() 
      .Where(k => _items.Contains(k)) 
      .Any(v => m_ExpectedData[ v ][ 0 ] != m_ExpectedData[ v ][ 1 ])); 
    } 
} 

}

一个例子,我有两个电话:

var asyncMgr = new AsyncDataManager(() => 
{ 
    // Code to run after all the async processes are complete 
}); 
asyncMgr.SetExpectation("Data1"); 
asyncMgr.SetExpectation("Data2"); 
m_DataProvider.GetData1(/* arguments for the call */, (results) => 
{ 
    // store the results, then tell asyncMgr that this process is complete 
    asyncMgr.ManageCallbacks("Data1"); 
}); 
m_DataProvider.GetData2(/* arguments for the call */, (results) => 
{ 
    // store the results, then tell asyncMgr that this process is complete 
    asyncMgr.ManageCallbacks("Data2"); 
}); 
-1

您应该使用异步回调

http://www.enterpriseetc.com/post/Three-Ways-to-Handle-Silverlight-Asynchronous-Service-Calls.aspx

然后,当工作完成后,将火的下一段代码,你告诉它

+0

我相信这个问题充分说明我知道我需要使用异步回调。问题是关于如何等待回调。提供的链接有一个“假同步”的过程,但它采用的是WaitOne的对象也没有定义或解释上,而且当时说,它“将完全冻结UI”。 –