C# 加载数据时ProgressBar未设置动画;使用wait时,加载不会等待

C# 加载数据时ProgressBar未设置动画;使用wait时,加载不会等待,c#,wpf,animation,progress-bar,async-await,C#,Wpf,Animation,Progress Bar,Async Await,在我的应用程序中,需要从数据库加载数据。在此期间,将显示一个启动屏幕。我想有一个进度条动画,所以添加到启动屏幕xaml这 <ProgressBar Margin="5" DockPanel.Dock="Top" IsIndeterminate="True" /> 因此,当getData1FromDB运行时,进度条动画停止。认为问题可以像这样解决 private async void loadData() { await Task.Run(() => getData1F

在我的应用程序中,需要从数据库加载数据。在此期间,将显示一个启动屏幕。我想有一个进度条动画,所以添加到启动屏幕xaml这

<ProgressBar Margin="5" DockPanel.Dock="Top" IsIndeterminate="True"  />
因此,当getData1FromDB运行时,进度条动画停止。认为问题可以像这样解决

private async void loadData()
{
   await Task.Run(() => getData1FromDB());
   displayData1_OnScreen();
   getData2FromDB();
   await Task.Run(() => displayData2_OnScreen());
   getData3FromDB();
   await Task.Run(() => displayData3_OnScreen());
}
这引起了另一个问题。getData1FromDB运行时,程序进入屏幕上的displayData1_。由于未完成getData1FromDB,因此未显示任何数据

如何在不重写整个加载过程的情况下解决此问题

编辑:基于评论

没有其他东西在屏幕上调用displayData1_,老实说,我也很惊讶。我唯一能想到的是loadData是从构造函数调用的

老实说,不,我不确定这就是问题所在。我正在尝试进行更多的调试,以了解@BradleyDotNET提出后实际发生了什么

关于getData1FromDB的问题有点难回答。基本上,它基于参数集构建一个sqlCMD字符串,然后像这样运行它

private void loadData()
{
    getData1FromDB();
    displayData1_OnScreen();
    getData2FromDB();
    displayData2_OnScreen();
    getData3FromDB();
    displayData3_OnScreen();
}
    DataTable dt = new DataTable();
string ConString = ConnectionString();
using (MySqlConnection con = new MySqlConnection(ConString))
{
    MySqlDataAdapter da = new MySqlDataAdapter();
    MySqlCommand cmd = new MySqlCommand(sqlCMD, con);
    con.Open();
    da.SelectCommand = cmd;
    da.Fill(dt);
    con.Close();
}
return dt;
除以下事件处理程序外,不应使用async void:

wpf中有动画,即使UI线程被阻塞,也可以在图形卡上运行,但它们非常有限,我不依赖它们

这个代码呢

private async Task loadData()
{
   await Task.Run(getData1FromDB);
   displayData1_OnScreen();

   await Task.Run(getData2FromDB);
   displayData2_OnScreen();

   await Task.Run(getData3FromDB);
   displayData3_OnScreen();
}

值得一提的是,即使loadData在构造函数中运行,下面的复制尝试似乎也能满足您的需要-

政务司司长:

XAML:


您发现了UI被阻止的第一个问题,我很惊讶在等待呼叫返回之前屏幕上的displayData1_运行。还有什么东西叫这个函数吗?你确定这就是问题所在吗这里实际上有两个问题。。第二个更有趣。。而且要想在标题中抓住[两者]是很难的。。咬的大小更容易处理,所以。你能发布getData1FromDB代码吗?不,他犯了一些错误。首先,他使用异步void。第二,他在UI线程中调用getData2FromDB和getData3FromDB,但在异步线程中在屏幕上显示Data2_,这没有意义。如果该方法是顶级方法,则为void是合适的。不管怎样,这都不会给他带来麻烦。至于其余的方法;它在达到那个点之前就出错了,所以这显然没有解决问题中描述的任何问题。好的,我明白了。我会删除我的答案,但我认为仍然有一些有用的观点
using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WpfAsyncAwaitProgressbar
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new TestViewModel();
        }
    }

    public class TestViewModel : INotifyPropertyChanged
    {
        public TestViewModel()
        {
            Text1 = Text2 = Text3 = "Loading ...";
            loadData();
        }

        public string Text1 { get; private set; }
        public string Text2 { get; private set; }
        public string Text3 { get; private set; }

        public Visibility ProgressbarVisibility { get; private set; }

        private async void loadData()
        {
            setBusyMode(true);
            await Task.Run(() => getData1FromDB());
            await Task.Run(() => getData2FromDB());
            await Task.Run(() => getData3FromDB());
            setBusyMode(false);
        }

        private void getData1FromDB()
        {
            Thread.Sleep(3000);
            Text1 = "Data Result 1";
            raisePropertyChanged(() => Text1);
        }

        private void getData2FromDB()
        {
            Thread.Sleep(2000);
            Text2 = "Data Result 2";
            raisePropertyChanged(() => Text2);
        }

        private void getData3FromDB()
        {
            Thread.Sleep(1000);
            Text3 = "Data Result 3";
            raisePropertyChanged(() => Text3);
        }

        private void setBusyMode(bool isBusy)
        {
            ProgressbarVisibility = isBusy ? Visibility.Visible : Visibility.Hidden;
            raisePropertyChanged(() => ProgressbarVisibility);
        }

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected void raisePropertyChanged<TProperty>(Expression<Func<TProperty>> projection)
        {
            var memberExpression = (MemberExpression)projection.Body;
            raisePropertyChanged(memberExpression.Member.Name);
        }

        private void raisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion INotifyPropertyChanged
    }
}
<Window x:Class="WpfAsyncAwaitProgressbar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight">
    <StackPanel>
        <TextBlock Text="{Binding Text1}"/>
        <TextBlock Text="{Binding Text2}"/>
        <TextBlock Text="{Binding Text3}"/>
        <ProgressBar Visibility="{Binding ProgressbarVisibility}"
                     IsIndeterminate="True"
                     Height="10"/>
    </StackPanel>
</Window>