Silverlight 4.0 等待Silverlight 4异步调用的最佳方式

Silverlight 4.0 等待Silverlight 4异步调用的最佳方式,silverlight-4.0,Silverlight 4.0,我正在努力为Silverlight 4应用程序获取数据。我的视图需要获取一些信息,因此它会调用我的数据提供者。我的数据提供商打电话给Oracle。这是一个需要回调的异步调用,因此我的DataProvider方法需要等待它。但是,如果在异步调用之后在DataProvider方法中放入Thread.Sleep循环,则回调永远不会命中。如果我删除Thread.Sleep循环,回调会命中,但到那时我的DataProvider方法已经完成,没有返回任何内容 异步性对视图没有价值;现在必须有这些数据才能继续

我正在努力为Silverlight 4应用程序获取数据。我的视图需要获取一些信息,因此它会调用我的数据提供者。我的数据提供商打电话给Oracle。这是一个需要回调的异步调用,因此我的DataProvider方法需要等待它。但是,如果在异步调用之后在DataProvider方法中放入Thread.Sleep循环,则回调永远不会命中。如果我删除Thread.Sleep循环,回调会命中,但到那时我的DataProvider方法已经完成,没有返回任何内容

异步性对视图没有价值;现在必须有这些数据才能继续。我希望能够弄清楚的是,如何让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" );
} );