C# 第一次导航到页面时阻止主线程 问题

C# 第一次导航到页面时阻止主线程 问题,c#,performance,user-interface,uwp,entity-framework-core,C#,Performance,User Interface,Uwp,Entity Framework Core,当应用程序启动时,将打开一个空的主页页面。我转到供应商选项卡,它会冻结几秒钟(我可以看到UI被冻结)。之后,将显示供应商页面。元素包含来自数据库的数据 您可能认为锁是由从数据库加载数据引起的。但是它出现在async/await方法中 如果在加载一个供应商后返回主页并返回供应商,则不会冻结。页面几乎立即打开。在这种情况下,数据加载机制也会发生(通过加载事件) 事实证明,只有在第一次访问Vendros页面时,冻结才是一个干净的开始。有什么问题吗 GIF 代码 查看 <i:Interactio

当应用程序启动时,将打开一个空的
主页
页面。我转到
供应商
选项卡,它会冻结几秒钟(我可以看到UI被冻结)。之后,将显示
供应商
页面。元素包含来自数据库的数据

您可能认为锁是由从数据库加载数据引起的。但是它出现在
async/await
方法中

如果在加载一个
供应商后返回
主页
并返回
供应商
,则不会冻结。页面几乎立即打开。在这种情况下,数据加载机制也会发生(通过
加载事件

事实证明,只有在第一次访问
Vendros
页面时,冻结才是一个干净的开始。有什么问题吗

GIF

代码 查看

<i:Interaction.Behaviors>
    <ic:EventTriggerBehavior EventName="Loaded">
        <ic:InvokeCommandAction Command="{x:Bind ViewModel.PageLoadedCommand}" />
    </ic:EventTriggerBehavior>
</i:Interaction.Behaviors>

供应商视图模型

public ICommand PageLoadedCommand {get;}
private async void OnPageLoaded(RoutedEventArgs args)
{
    await VendorsService.InitializeAsync();

    BankItems = VendorsService.BankItems;
    AuthorityItems = VendorsService.AuthorityItems;
    VendorItems = VendorsService.VendorItems;
}

public ObservableCollection<VendorModel> VendorItems {get; set;}
public ObservableCollection<TwoLinesModel> BankItems {get; set;}
public ObservableCollection<TwoLinesModel> AuthorityItems{get; set;}
public partial class GenericDataService<T> : IDataService<T> where T : DomainEntity
{
    private readonly DbContext _dbContext;
    public GenericDataService(DbContext dbContext) => _dbContext = dbContext;

    public async Task<IList<T>> SelectAll()
    {
        return await _dbContext.Set<T>().ToListAsync();
    }
}
public ICommand PageLoadedCommand{get;}
已加载页面上的专用异步无效(RoutedEventArgs args)
{
等待VendorsService.InitializeAsync();
BankItems=VendorsService.BankItems;
AuthorityItems=供应商服务.AuthorityItems;
VendorItems=VendorService.VendorItems;
}
公共ObservableCollection供应商项{get;set;}
公共ObservableCollection银行项目{get;set;}
公共ObservableCollection AuthorityItems{get;set;}
供应商服务

private TwoLinesService<BankEntity> BankService { get; } = new TwoLinesService<BankEntity>();
private TwoLinesService<AuthorityEntity> AuthorityService { get; } = new TwoLinesService<AuthorityEntity>();

public ObservableCollection<VendorModel> VendorItems { get; private set; }
public ObservableCollection<TwoLinesModel> BankItems { get; private set; }
public ObservableCollection<TwoLinesModel> AuthorityItems { get; private set; }

public async Task InitializeAsync()
{
    await BankService.InitializeAsync();
    await AuthorityService.InitializeAsync();

    VendorItems = new ObservableCollection<VendorModel>
    {
        new VendorModel { Name = "Name 1", Surname = "Surname 1", Patronymic = "MiddleName 1", IssueDate = new DateTime(2020, 2, 9) },
        new VendorModel { Name = "Name 2", Surname = "Surname 2", Patronymic = "MiddleName 2", IssueDate = new DateTime(2019, 3, 7) }
    };
    BankItems = BankService.Items;
    AuthorityItems = AuthorityService.Items;

    await Task.CompletedTask;
}
public class TwoLinesService<TEntity> 
    where TEntity : TwoLinesEntity, new()
{
    private IDataServiceFactory<TEntity> DataServiceFactory { get; } = new DataServiceFactory<TEntity>();
    public ObservableCollection<TwoLinesModel> Items { get; } = new ObservableCollection<TwoLinesModel>();

    public async Task InitializeAsync()
    {
        using var dataService = DataServiceFactory.Create();

        foreach (var entity in await dataService.SelectAll())
        {
            Items.Add(CreateModel(entity));
        }

        await Task.CompletedTask;
    }

    public TwoLinesModel CreateModel(TEntity source)
    {
        return new TwoLinesModel
        {
            ID = source.ID,
            Title = source.Title,
            Text = source.Text,
            CreatedOn = source.CreatedOn,
            LastModifiedOn = source.LastModifiedOn
        };
    }
}
private TwoLinesService银行服务{get;}=new TwoLinesService();
private TwoLinesService AuthorityService{get;}=new TwoLinesService();
公共可观测集合供应商项{get;private set;}
public observeCollection BankItems{get;private set;}
公共ObservableCollection AuthorityItems{get;private set;}
公共异步任务InitializeAsync()
{
wait BankService.InitializeAsync();
等待AuthorityService.InitializeAsync();
VendorItems=新的可观察集合
{
新的供应商模型{Name=“Name 1”,姓氏=“Name 1”,赞助人=“MiddleName 1”,发布日期=新的日期时间(2020,2,9)},
新供应商模型{Name=“Name 2”,姓氏=“Name 2”,赞助人=“MiddleName 2”,发布日期=新日期时间(2019,3,7)}
};
BankItems=BankService.Items;
AuthorityItems=AuthorityService.Items;
等待任务。完成任务;
}
TwoLinesService

private TwoLinesService<BankEntity> BankService { get; } = new TwoLinesService<BankEntity>();
private TwoLinesService<AuthorityEntity> AuthorityService { get; } = new TwoLinesService<AuthorityEntity>();

public ObservableCollection<VendorModel> VendorItems { get; private set; }
public ObservableCollection<TwoLinesModel> BankItems { get; private set; }
public ObservableCollection<TwoLinesModel> AuthorityItems { get; private set; }

public async Task InitializeAsync()
{
    await BankService.InitializeAsync();
    await AuthorityService.InitializeAsync();

    VendorItems = new ObservableCollection<VendorModel>
    {
        new VendorModel { Name = "Name 1", Surname = "Surname 1", Patronymic = "MiddleName 1", IssueDate = new DateTime(2020, 2, 9) },
        new VendorModel { Name = "Name 2", Surname = "Surname 2", Patronymic = "MiddleName 2", IssueDate = new DateTime(2019, 3, 7) }
    };
    BankItems = BankService.Items;
    AuthorityItems = AuthorityService.Items;

    await Task.CompletedTask;
}
public class TwoLinesService<TEntity> 
    where TEntity : TwoLinesEntity, new()
{
    private IDataServiceFactory<TEntity> DataServiceFactory { get; } = new DataServiceFactory<TEntity>();
    public ObservableCollection<TwoLinesModel> Items { get; } = new ObservableCollection<TwoLinesModel>();

    public async Task InitializeAsync()
    {
        using var dataService = DataServiceFactory.Create();

        foreach (var entity in await dataService.SelectAll())
        {
            Items.Add(CreateModel(entity));
        }

        await Task.CompletedTask;
    }

    public TwoLinesModel CreateModel(TEntity source)
    {
        return new TwoLinesModel
        {
            ID = source.ID,
            Title = source.Title,
            Text = source.Text,
            CreatedOn = source.CreatedOn,
            LastModifiedOn = source.LastModifiedOn
        };
    }
}
公共类TwoLinesService
其中tenty:twolencentity,new()
{
私有IDataServiceFactory DataServiceFactory{get;}=new DataServiceFactory();
公共ObservableCollection项{get;}=new ObservableCollection();
公共异步任务InitializeAsync()
{
使用var-dataService=dataservicecfactory.Create();
foreach(wait-dataService.SelectAll()中的var实体)
{
添加(CreateModel(实体));
}
等待任务。完成任务;
}
公共TwoLinesModel CreateModel(TEntity源)
{
返回新的TwoLinesModel
{
ID=source.ID,
Title=source.Title,
Text=source.Text,
CreatedOn=source.CreatedOn,
LastModifiedOn=source.LastModifiedOn
};
}
}
DataServiceFactory

public class DataServiceFactory<T> : IDataServiceFactory<T> where T : DomainEntity
{
    public IDataService<T> Create()
    {
        return Configuraiton.Current.DataProvider switch
        {
            DataProviderType.SQLite => new SQLiteService<T>(Configuraiton.Current.SQLiteConnectionString),
            _ => throw new NotImplementedException()
        };
    }
}
公共类DataServiceFactory:IDataServiceFactory其中T:DomainEntity
{
公共IDataService创建()
{
返回Configurationon.Current.DataProvider开关
{
DataProviderType.SQLite=>新的SQLiteService(ConfigurationOn.Current.SQLiteConnectionString),
_=>抛出新的NotImplementedException()
};
}
}
选择全部()

公共部分类GenericDataService:IDataService其中T:DomainEntity
{
私有只读dbcontextu DbContext;
公共通用数据服务(DbContext DbContext)=>\u DbContext=DbContext;
公共异步任务SelectAll()
{
返回wait_dbContext.Set().toListSync();
}
}

这可能是UWP异步编程中的常见陷阱。使用async/await/Task并不等同于在后台线程中运行代码。如果希望在后台线程中执行一些耗时的任务,则需要将其包装在task.Run()中。否则UI线程将被阻止

请尝试使用Task.anyway中的SelectAll()运行

public Task<IList<T>> SelectAll()
{
    return Task.Run(async ()=> { return await _dbContext.Set<T>().ToListAsync(); });
}
public任务SelectAll()
{
return Task.Run(async()=>{return await_dbContext.Set().ToListAsync();});
}
说明 我设法找到了瓶颈。该项目是开发的早期阶段。在启动期间,程序不会调用与数据库关联的方法。我在帮助下检测到第一次调用DataServiceFactory.Create()时加载了新组件。在此之后,用户界面冻结立即结束

"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Threading.Tasks.Extensions.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Linq.Expressions.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Resources.ResourceManager.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Diagnostics.Tracing.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.ComponentModel.TypeConverter.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "Anonymously Hosted DynamicMethods Assembly". 
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Data.Common.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.ComponentModel.Primitives.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Transactions.Local.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.ComponentModel.Annotations.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Threading.Timer.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Threading.Thread.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Text.RegularExpressions.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Buffers.dll".
"ProgramName.exe" (CoreCLR: CoreCLR_UWP_Domain). Loaded "C:\Program Files\WindowsApps\Microsoft.NET.CoreFramework.Debug.2.2_2.2.27909.0_x64__8wekyb3d8bbwe\System.Memory.dll".
解决方案 主要的解决方案是在启动时加载数据。在这个阶段,没有要加载的内容

我找到两个临时解决办法

  • App.xaml.cs
    中调用工厂创建。这将加载大多数组件

DataServiceFactory.Create()
dataService.SelectAll()
中的内容。你有什么理由叫它两次,或者那只是一个打字错误吗?@Euphoric是的,就是打字错误。我添加了代码。