MVVM 调度程序 UI 没有响应

MVVM Dispatcher UI not responisve

我 运行 在一个可能很简单的问题中:

我用 MVVM light 构建了一个 MVVM 应用程序。

当我进行大量计算时,我的 UI 没有响应。 我需要一个调度程序,因为我想访问一些依赖对象。

我尝试使用该代码:(可能无法工作,因为我使用的是应用程序线程?!)

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
            {
                //LongTimeStuff
            }));

我也试过:

        DispatcherHelper.Initialize();
        DispatcherHelper.CheckBeginInvokeOnUI(() =>
        {
             //LongTimeStuff
        });

但是这里我遇到了问题,我的依赖对象在另一个线程中。

我在新线程的函数中所做的所有这些事情:

   Thread CalculationThread = new Thread(this.Calculate);

谢谢!

运行 新 Thread/Task 中的长期内容,只要您需要访问依赖对象,然后调用主线程,例如:

private void button_Click(object sender, RoutedEventArgs e)
    {          
        Task.Run(() => {
            Thread.Sleep(3000);
            //LongTimeStuff
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
            {
                textBlock1.Text = "10";

            }));
        });
    }

Dispatcher BeginInvoke 或 InvokeAsync 没有 运行 任何东西都是单独的线程。它只将任务添加到 Dispatcher 任务队列。但是调度程序队列总是在 UI 线程上处理。

这是你应该做的:

void CommandExecuted()
{
   Task.Run(() =>
   {
     //long running stuff

     Dispatcher.BeginInvoke(new Action(() =>
     {
       //access ui here
     }));
}

或使用异步模式:

    async void CommandExecuted()
    {
        await Task.Run(() =>
        {
            //long running stuff
        });
        //access ui here
    }

尝试更改 DispatcherPriority,如果您计划在之前开始处理另一个线程,则不需要 BeginInvoke:

        Task.Factory.StartNew(() =>
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(2000);
                //LongTimeStuff
                Application.Current.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(() =>
                {
                    textblock.Text = DateTime.Now.ToString();

                }));
            }
        });

您需要在另一个线程中完成工作,然后使用调度程序在完成后更新您的 UI。这是一些演示的 C# 伪代码。

// we're in the UI thread here
PleaseWait = true; // indicate to the user we'll be back soon
var whatever = GetStuffFromTheUIThatWeNeedInTheOtherThreadLol();
Task.Run(() => 
{
    // here we're on a background thread
    var result = OurLongRunningOperation(whatever);
    Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal, new Action(() =>
    {
        // we're back on the UI thread here
        UpdateUIWithResultsOfLongTimeOperationDerp(result);
        PleaseWait = false;
    }));
});
// snip

我得到了答案:

首先 - 我确实从 Dispatcher 中取出了我的 "LongTimeStuff"。

其次 - 我已经做了:Task.Sleep(1); 在我的循环中,突然它起作用了。 想知道为什么但它有效!