Multithreading 在Silverlight页面之间导航时在大型机上显示IsBusy指示灯

Multithreading 在Silverlight页面之间导航时在大型机上显示IsBusy指示灯,multithreading,silverlight-4.0,navigation,Multithreading,Silverlight 4.0,Navigation,我使用的是Silverlight 4导航框架,页面的加载需要一些时间(通常绑定到大量数据) 我在大型机上放置了一个IsBusy SL Toolkit控件,我想在您单击导航到另一个页面时将其设置为Busy,并在另一个页面完成加载后将其设置为NotBusy 为了保持简单并首先让它工作,我排除了MVVM,只使用代码隐藏调用,但我的IsBusy控件从未出现。我想这是一个UI线程问题,但我需要一些帮助 编辑:在一个简单的页面上,IsBusy控件会出现,但只有在加载请求的页面后才会出现(然后它被关闭,因此您

我使用的是Silverlight 4导航框架,页面的加载需要一些时间(通常绑定到大量数据)

我在大型机上放置了一个IsBusy SL Toolkit控件,我想在您单击导航到另一个页面时将其设置为Busy,并在另一个页面完成加载后将其设置为NotBusy

为了保持简单并首先让它工作,我排除了MVVM,只使用代码隐藏调用,但我的IsBusy控件从未出现。我想这是一个UI线程问题,但我需要一些帮助

编辑:在一个简单的页面上,IsBusy控件会出现,但只有在加载请求的页面后才会出现(然后它被关闭,因此您永远看不到它)。我需要调用页在父帧上调用IsBusy控件,并在它尝试加载下一页之前显示它

以下是我的大型机页面上的XAML:

   <Grid x:Name="LayoutRoot">
        <navigation:Frame
            x:Name="ContentFrame"... NavigationFailed="ContentFrame_NavigationFailed">
            <navigation:Frame.UriMapper>
                   ...
            </navigation:Frame.UriMapper>
        </navigation:Frame>

        <telerik:RadBusyIndicator
            x:Name="busyIndicator"
            BusyContent="Please wait..." />
    </Grid>
然后在目标页面上:

    public WorkOrderView()
    {
        InitializeComponent();

        ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false;
    }
我尝试了很多不同的选择,但指示器从未出现。我尝试用一些线程代码包装它,然后它显示出来,但抛出了一个无效的跨线程异常

我使用以下代码(同一页面上的一个按钮)测试了XAML,它工作正常(显示和隐藏):

我确信这与UI线程有关。。。感谢您的帮助


谢谢

我建议您查看Silverlight 4中引入的
INavigationContentLoader
界面,它为您提供了一个很好的地方,可以连接到导航系统并“全局”(跨所有导航)执行类似的操作

请参阅David Poll的博客文章《做一些非常类似的事情》,这里:

他正在做的事情比你需要的要复杂得多(从远程XAP加载页面),但看看他在用BusyIndicator控件做什么,希望很容易看到如何剥离和使用这一部分(他提供了他所有东西的源代码,所以你可以随心所欲地挖掘)


如果这看起来比您的项目所需的工作量更多,那么您可以通过另一种方式完成它,即挂接到
Frame.Navigated
Frame.Navigating
-在承载该框架的控件上创建一个布尔属性,在
框架中将其设置为true。在
框架中导航
并返回到false。在
框架中导航
并使用数据绑定将该布尔属性绑定到IsBusy控件。

再次感谢Austin,我将研究它。我真的很好奇为什么这不起作用,尽管它是最简单的形式。我注意到,在一个简单的页面上,IsBusy指示器实际上是在显示的,但只在它导航的页面上显示(它在它的构造函数中进行了大量加载)。我希望它显示在调用页面上(它实际上在frame元素上,它只是从调用页面调用的)。这与UI线程有关,我真的很想理解它……我想你是对的,UI线程被锁定了。实现INavigationContentLoader可以让您更灵活地控制计时,但一个问题是,如果您的页面在UI线程上做了大量工作,它将锁定UI(至少在桌面上,Windows Phone版本的Silverlight在这里更好,有一个单独的渲染线程,希望它能进入Silverlight 5)。我能说的最好的方法是尝试使复杂的工作(大数据分析等…)发生在后台线程上以最小化此问题。好的,谢谢-在我将IsBusy设置为true后调用线程暂停,这样它就会显示框,然后开始复杂的加载。听起来非常有黑客味!任何阻止线程的操作都会导致同样的问题。我想说试试我上面的方法,看看是否可以您仍然看到了问题。如果是这样,发布更多的代码可能会有所帮助-比如显示页面的运行情况,甚至导致UI线程锁定。罪魁祸首代码是Effiproz隔离存储数据库。我们从Web服务中检索了约60兆的数据,并在签出时将其写入本地数据库。然后,用户可以在断开连接的情况下工作CTE,稍后再检查。一旦它从本地DB写入/读取,它就会阻塞线程,因此现在我尝试使用BackgroundWorker进行网格加载(我在Telerik网格上使用虚拟化,因此这不是绑定的错误)。我面临着很大的时间压力,因此我需要尽快让它工作(尽管我最终还是想看看Nav框架解决方案!)
    public WorkOrderView()
    {
        InitializeComponent();

        ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false;
    }
    private void btnIsBusy_Click(object sender, RoutedEventArgs e)
    {
        ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = true;
        ThreadPool.QueueUserWorkItem((state) =>
        {
            Thread.Sleep(3 * 1000);
            Dispatcher.BeginInvoke(() => ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false);
        });
    }