Silverlight 4.0 等待Silverlight 4异步调用的最佳方式
我正在努力为Silverlight 4应用程序获取数据。我的视图需要获取一些信息,因此它会调用我的数据提供者。我的数据提供商打电话给Oracle。这是一个需要回调的异步调用,因此我的DataProvider方法需要等待它。但是,如果在异步调用之后在DataProvider方法中放入Thread.Sleep循环,则回调永远不会命中。如果我删除Thread.Sleep循环,回调会命中,但到那时我的DataProvider方法已经完成,没有返回任何内容 异步性对视图没有价值;现在必须有这些数据才能继续。我希望能够弄清楚的是,如何让DataProvider类对来自视图的一个请求进行多次数据库调用,直到它准备好后才返回。在这种情况下,我不介意视图没有响应性;但我的做法是完全锁定应用程序 这就是我所拥有的: 视图发出以下调用:Silverlight 4.0 等待Silverlight 4异步调用的最佳方式,silverlight-4.0,Silverlight 4.0,我正在努力为Silverlight 4应用程序获取数据。我的视图需要获取一些信息,因此它会调用我的数据提供者。我的数据提供商打电话给Oracle。这是一个需要回调的异步调用,因此我的DataProvider方法需要等待它。但是,如果在异步调用之后在DataProvider方法中放入Thread.Sleep循环,则回调永远不会命中。如果我删除Thread.Sleep循环,回调会命中,但到那时我的DataProvider方法已经完成,没有返回任何内容 异步性对视图没有价值;现在必须有这些数据才能继续
m_Data = m_DataProvider.GetMyStuffData( some parameters to filter the data );
数据提供程序识别参数并开始构建m_数据对象。这需要许多调用,其中一个如下所示:
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;
}
public覆盖列表GetMyStuff(DateTime\u startDay,DateTime\u endDay)
{
var rc=新列表();
m_WaitingForData=真;
var query=MyQueryString;
var parameters=新字符串[]{“我的参数”};
getOracleData(参数,查询,“我的查询ID”);
while(m_WaitingForData)
{
睡眠(20);
}
//处理异步调用放入成员变量的数据。
返回rc;
}
getOracleData进行异步调用,将回调连接到GetTable
回调方法GetTable将数据提取到GetMyStuff期望的成员变量中,关闭m_WaitingForData并退出。您应该使用异步回调
然后,当作业完成时,它将触发您告诉它的下一段代码我最终开发了这个小类:
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 ] ) );
}
}
我相信这个问题充分表明我知道我需要使用异步回调。问题是如何等待回调。提供的链接有一个“假同步”进程,但它在一个未定义或解释的对象上使用WaitOne,甚至说它“将完全冻结UI”。
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" );
} );