如何让我的应用程序等待我的UI刷新?

时间:2013-02-11 15:42:19

标签: c# wpf

在不使用额外线程的情况下,我只想在读取或写入大量数据时显示“加载”标签或与用户类似的内容。但是,如果我尝试在调用IO方法之前修改任何UI元素,应用程序会冻结一段时间,然后在之后显示“加载”消息已完成所有工作。这显然无济于事。如何在调用IO方法之前确保应用任何UI更改并显示

        DataSet ds = STT_Import.ImportExcelToDataSet(filePath);

        bool result = false;

        if (ds != null)
        {
            int cellCount = ds.GetTotalCellCount();

            if (Popup.ShowMessage(string.Format("Your file contains {0} cells. Inserting data will take approximately {1} seconds. Do you want to continue?",
                cellCount, CalculateTime(cellCount)), "Confirm", MessageType.Confirm) == MessageBoxResult.Yes)
            {
                // Tell user the application is working:
                StatusLabel.Content = "Writing to database...";

                // Do actual work after user has been notified:
                result = DB.StoreItems(_currentType, ds);
            }
        }

我尝试寻找答案,却找不到任何能回答我具体问题的答案,所以如果以前问过这个问题,我很抱歉。

5 个答案:

答案 0 :(得分:1)

使用WPF时,您可以使用Dispatcher在不同DispatcherPriorities的UI线程上排队命令

这将允许您在{/ 1}}或DispatcherPriority.Render队列中的所有内容后,在UI线程上对长时间运行的进程进行排队。

例如,您的代码可能如下所示:

DispatcherPriority.Loaded

应该注意的是,它通常被认为是在运行时锁定应用程序的糟糕设计。

更好的解决方案是在后台线程上运行长时间运行的进程,并在运行时简单地禁用应用程序表单。有很多方法可以做到这一点,但我个人的偏好是使用Task Parallel Library,因为它很简单。

例如,使用后台线程的代码如下所示:

// Tell user the application is working:
StatusLabel.Content = "Writing to database...";

// Do actual work after user has been notified:
Dispatcher.BeginInvoke(DispatcherPriority.Input,
    new Action(delegate() { 
        var result = DB.StoreItems(_currentType, ds);     // Do Work
        if (result)
            StatusLabel.Content = "Finished";
        else
            StatusLabel.Content = "An error has occured";
     }));

答案 1 :(得分:0)

您正在使用的方法效率不高,所以建议您使用异步编程或线程

异步编程:

Visual Studio 2012引入了一种简化的方法,即异步编程,它利用.NET Framework 4.5和Windows运行时中的异步支持。编译器执行开发人员过去所做的艰巨工作,并且您的应用程序保留了类似于同步代码的逻辑结构。因此,您可以通过一小部分工作获得异步编程的所有优势。支持.Net框架4.5
它将节省您实施System。线程的时间,并且非常有效地完成与我们必须等待某些操作的任务相同的任务

http://msdn.microsoft.com/en-ca/library/vstudio/hh191443.aspx
http://go.microsoft.com/fwlink/?LinkID=261549

线程:

线程的优点是能够创建使用多个执行线程的应用程序。例如,进程可以有一个用户界面线程来管理与用户和工作线程的交互,这些线程在用户界面线程等待用户输入时执行其他任务。支持.Net fremework 4.0或更早版本

http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx

答案 2 :(得分:0)

您正试图以错误的方式解决问题。你应该在这里做的是在工作线程中运行耗时的任务;这样,您的用户界面将保持响应当前的问题将变得没有实际意义。

有几种方法可以将任务卸载到工作线程;最方便的是using the thread poolasynchronous programming

答案 3 :(得分:0)

除非您的数据库提供您正在使用的方法的异步版本,否则在不使用其他线程的情况下保持UI响应是不可能的。如果它 提供该方法的异步版本,那么您只需要使用它。 (请记住,async确实意味着它正在使用任何其他线程。完全有可能创建一个永远不会使用其他线程的异步方法,并且完全完成了什么大多数网络IO方法。)如何执行此操作的具体细节取决于您正在使用的数据库框架的类型,以及您如何使用它。

如果您的数据库框架不提供异步方法,那么保持UI响应的唯一方法是在非UI线程中执行长时间运行的操作。

答案 4 :(得分:0)

如果您不希望UI响应,我会使用忙碌指示符 有更漂亮的游标 - 这是一个内部应用程序。

using (new WaitCursor())
{
    // very long task
    Search.ExecuteSearch(enumSrchType.NextPage);
}

public class WaitCursor : IDisposable
{
    private Cursor _previousCursor;

    public WaitCursor()
    {
        _previousCursor = Mouse.OverrideCursor;

        Mouse.OverrideCursor = Cursors.Wait;
    }

    #region IDisposable Members

    public void Dispose()
    {
        Mouse.OverrideCursor = _previousCursor;
    }

    #endregion
}