gpt4 book ai didi

c# - Wpf 应用程序卡住 - 大量内存泄漏之谜

转载 作者:太空狗 更新时间:2023-10-29 19:43:33 24 4
gpt4 key购买 nike

我有一个 mvvm wpf 应用程序,它一直正常工作,直到它卡住并导致大量内存泄漏的那一刻。解决方案文件: Google Disk Solution Link

应用程序使用本地 mdf 文件,使用 Mahhaps 和一些额外的引用(例如用于显示 gif 的引用)

enter image description here

这是造成问题的 View 模型中的方法调用,使用 await 分配联系人是造成问题的 - 这在另一个 View 模型中使用,它没有任何问题,即使在这里它正在工作好吧,直到一会儿。

public async  void OnLoad()
{
IsRefreshEnabled = false;
IsRefreshProgressActive = true;
Contacts =await Task.Run(() => _repository.GetContactsAsync()) ;
IsRefreshEnabled = true;
IsRefreshProgressActive = false;
}

这是View的渲染方式

<DataGrid SelectedItem="{Binding Contact}" AutoGenerateColumns="True" ItemsSource="{Binding Path=Contacts, Mode=TwoWay}" Style="{StaticResource AzureDataGrid}"  x:Name="dataGridCodeBehind"  Margin="10,54,521,0" VerticalAlignment="Top"  HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ColumnWidth="*">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="FontSize" Value="10"/>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>

我尝试删除 gif 的库(gif 未显示在此 View 中,而在另一个 View 中没有出现任何问题)。

对存储库的相同调用 - 以获取我在另一个 View 中拥有的联系人数据,并且没有产生任何问题。

这个 Contacts View 一直很好用,直到突然之间。

我尝试调试,但调试器甚至没有找到代码。

将一些数据加载到数据库后,我卡住了。

卡住是由 ContactsViewModel 中的 OnLoad 方法完成的 - 这个对存储库的调用用于另一个没有任何问题的 ViewModel - 它快速返回数据

ContactsViewModel代码:

using Digital_Data_House_Bulk_Mailer.Commands;
using Digital_Data_House_Bulk_Mailer.Model;
using Digital_Data_House_Bulk_Mailer.Repository;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace Digital_Data_House_Bulk_Mailer.ViewModel
{
class ContactsViewModel : INotifyPropertyChanged
{
private Contact _contact;

private IContactRepository _repository = new ContactRepository();

public event PropertyChangedEventHandler PropertyChanged = delegate { };

public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

private static void NotifyStaticPropertyChanged(string propertyName)
{
if (StaticPropertyChanged != null)
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}

public RelayCommand UpdateCommand { get; set; }

public RelayCommand LoadCommand { get; set; }

public RelayCommand DeleteCommand { get; set; }

public RelayCommand DeleteAllContactsCommand { get; set; }

public RelayCommand RecreateFiltersCommand { get; set; }

private ObservableCollection<Contact> _contacts;

public ObservableCollection<Contact> Contacts
{
get { return _contacts; }
set
{
_contacts = value;
PropertyChanged(this, new PropertyChangedEventArgs("Contacts"));
//used in case of static Contacts property
//NotifyStaticPropertyChanged("Contacts");
}
}


public Contact Contact
{
get { return _contact; }
set
{
_contact = value;
DeleteCommand.RaiseCanExecuteChanged();
UpdateCommand.RaiseCanExecuteChanged();
PropertyChanged(this, new PropertyChangedEventArgs("Contact"));
}
}

private bool _isRefreshEnabled=true;
public bool IsRefreshEnabled
{
get { return _isRefreshEnabled; }
set
{
_isRefreshEnabled = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsRefreshEnabled"));
}
}

private bool _isRefreshProgressActive = false;
public bool IsRefreshProgressActive
{
get { return _isRefreshProgressActive; }
set
{
_isRefreshProgressActive = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsRefreshProgressActive"));
}
}

public ContactsViewModel()
{
DeleteCommand = new RelayCommand(OnDelete, CanDelete);
UpdateCommand = new RelayCommand(OnUpdate, CanUpdate);
LoadCommand = new RelayCommand(OnLoad, CanLoad);
DeleteAllContactsCommand = new RelayCommand(OnDeleteAllContacts, CanDeleteAllContacts);
RecreateFiltersCommand = new RelayCommand(OnRecreateFilters, CanRecreateFilters);
OnLoad();
}

public bool CanRecreateFilters()
{
return true;
}

public async void OnRecreateFilters()
{
IsRefreshProgressActive = true;
await Task.Run(() => _repository.ResetFilters());
IsRefreshProgressActive = false;
}

public async void OnDeleteAllContacts()
{
MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "DELETE ALL EXISTING CONTACTS", System.Windows.MessageBoxButton.YesNo);
if (messageBoxResult == MessageBoxResult.Yes)
{
IsRefreshProgressActive = true;
await Task.Run(() => _repository.DeleteAllContacts());
IsRefreshProgressActive = false;
}
}

public bool CanDeleteAllContacts()
{
return true;
}


private void OnDelete()
{
MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "Delete Contact Confirmation", System.Windows.MessageBoxButton.YesNo);
if (messageBoxResult == MessageBoxResult.Yes)
{
_repository.DeleteContactAsync(Contact);
Contacts.Remove(Contact);
}
}

private bool CanDelete()
{
if (Contact != null )
{
return true;
}
return false;
}

private void OnUpdate()
{
_repository.AddContactAsync(Contact);

}

private bool CanUpdate()
{
if (Contact != null )
{
return true;
}
return false;
}


public async void OnLoad()
{
IsRefreshEnabled = false;
IsRefreshProgressActive = true;
Contacts =await Task.Run(() => _repository.GetContactsAsync()) ;
IsRefreshEnabled = true;
IsRefreshProgressActive = false;
}

private ObservableCollection<Contact> GetContactsAsync()
{
return _repository.GetContactsAsync();
}

public bool CanLoad()
{
return true;
}

}
}

ContactRepository 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Digital_Data_House_Bulk_Mailer.Model;
using System.Data.Entity;
using System.Collections.ObjectModel;
using System.Data.Entity.Migrations;
using System.Collections;
using System.Data.Entity.Core.Objects;
using System.Data.SqlClient;

namespace Digital_Data_House_Bulk_Mailer.Repository
{
class ContactRepository : IContactRepository
{
digital_datahouse_bulk_mailerEntities db = null;

public ContactRepository()
{
db = new digital_datahouse_bulk_mailerEntities();
}

public string SELECT_ALL { get { return "Select All"; } private set { } }


public ObservableCollection<StateFilter> GetStates()
{

ObservableCollection<StateFilter> stateFilters = new ObservableCollection<StateFilter>();

foreach (StateFilter state in db.StateFilters.ToList() )
{
db.Entry<StateFilter>(state).Reload();
stateFilters.Add(state);
}



return stateFilters;
}

public ObservableCollection<CountyFilter> GetCounties()
{
ObservableCollection<CountyFilter> countyFilters = new ObservableCollection<CountyFilter>();

foreach (CountyFilter county in db.CountyFilters.ToList())
{
db.Entry<CountyFilter>(county).Reload();
countyFilters.Add(county);
}

return countyFilters;
}

public ObservableCollection<GenderFilter> GetGenders()
{
ObservableCollection<GenderFilter> genderFilters = new ObservableCollection<GenderFilter>();

foreach (GenderFilter gender in db.GenderFilters.ToList())
{
db.Entry<GenderFilter>(gender).Reload();
genderFilters.Add(gender);
}

return genderFilters;
}

public ObservableCollection<IndustryFilter> GetIndustries()
{
ObservableCollection<IndustryFilter> industryFilters = new ObservableCollection<IndustryFilter>();

foreach (IndustryFilter industry in db.IndustryFilters.ToList())
{
db.Entry<IndustryFilter>(industry).Reload();
industryFilters.Add(industry);
}

return industryFilters;
}

public ObservableCollection<IsContactedFilter> GetIsContacted()
{
ObservableCollection<IsContactedFilter> isContactedFilters = new ObservableCollection<IsContactedFilter>();

foreach (IsContactedFilter isContacted in db.IsContactedFilters.ToList())
{
db.Entry<IsContactedFilter>(isContacted).Reload();
isContactedFilters.Add(isContacted);
}

return isContactedFilters;
}

public ObservableCollection<SicCodeDescriptionFilter> GetSicCodeDescriptions()
{
ObservableCollection<SicCodeDescriptionFilter> sicCodeDescriptionFilters = new ObservableCollection<SicCodeDescriptionFilter>();

foreach (SicCodeDescriptionFilter sicCodeDescriptionFilter in db.SicCodeDescriptionFilters.ToList())
{
db.Entry<SicCodeDescriptionFilter>(sicCodeDescriptionFilter).Reload();
sicCodeDescriptionFilters.Add(sicCodeDescriptionFilter);
}

return sicCodeDescriptionFilters;
}



public void AddContactAsync(Contact contact)
{
if (contact != null)
{
db.Contacts.AddOrUpdate(contact);
db.SaveChangesAsync();
}
}

public void DeleteContactAsync(Contact contact)
{
if (contact != null)
{
db.Contacts.Remove(contact);
db.SaveChangesAsync();
}
}

public void UpdateContactAsync(Contact contact)
{
if (contact != null)
{
db.Contacts.AddOrUpdate(contact);
db.SaveChangesAsync();
}
}

public ObservableCollection<Contact> GetContactsAsync()
{

db = new digital_datahouse_bulk_mailerEntities();

ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();

foreach (var contact in db.Contacts.ToList())
{
contacts.Add(contact);
}
return contacts;
}

public ObservableCollection<Contact> FilterContacts(ObservableCollection<StateFilter> states, ObservableCollection<CountyFilter> counties,
ObservableCollection<GenderFilter> genders, ObservableCollection<IndustryFilter> industries, ObservableCollection<IsContactedFilter> contacted,
ObservableCollection<SicCodeDescriptionFilter> codes, bool hasWebsite)
{

db = new digital_datahouse_bulk_mailerEntities();

ObservableCollection<Contact> filteredContacts = new ObservableCollection<Contact>();

string[] stateArray = (from s in states where s.IsChecked==true select s.State).ToArray();
string[] countyArray= (from c in counties where c.IsChecked==true select c.County).ToArray();
string[] genderArray= (from g in genders where g.IsChecked==true select g.Gender).ToArray();
string[] industryArray = (from i in industries where i.IsChecked==true select i.Industry).ToArray();
string[] contactedArray = (from c in contacted where c.IsChecked==true select c.IsContacted.ToString()).ToArray();
string[] sicCodeArray = (from c in codes where c.IsChecked==true select c.SicCodeDescription).ToArray();

var contacts=(from c in db.Contacts
where
stateArray.Contains(c.State) &&
countyArray.Contains(c.County) &&
genderArray.Contains(c.Gender) &&
industryArray.Contains(c.Industry) &&
contactedArray.Contains(c.IsContacted) &&
sicCodeArray.Contains(c.SIC_Code_Description)

select c).ToList();

foreach (Contact contact in contacts)
{
if(hasWebsite==true)
{
if(!String.IsNullOrEmpty(contact.WebSite))
{
filteredContacts.Add(contact);
}
}
else
{
filteredContacts.Add(contact);
}

}

return filteredContacts;
}

public void AddContactsRange(ObservableCollection<Contact> contacts)
{

db.Contacts.AddRange(contacts);
db.SaveChanges();

}

public void ResetFilters()
{
ResetStates();
ResetCounties();
ResetIsContactedFilters();
ResetGenders();
ResetIndustries();
ResetSicFilters();

}

private void ResetStates()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [StateFilter]");

db = new digital_datahouse_bulk_mailerEntities();

List<StateFilter> stateFilters = new List<StateFilter>();

var states = (
from c in db.Contacts
select c.State

).Distinct().ToList();

foreach (var stateName in states)
{
StateFilter state = new StateFilter();
state.State = stateName;
state.IsChecked = true;
stateFilters.Add(state);

}


db.StateFilters.AddRange(stateFilters);
db.SaveChanges();

}

public void DeleteAllContacts()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [Contact]");
db = new digital_datahouse_bulk_mailerEntities();
}

private void ResetCounties()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [CountyFilter]");
db = new digital_datahouse_bulk_mailerEntities();

List<CountyFilter> countyFilters = new List<CountyFilter>();

var counties = (
from c in db.Contacts
select c.County

).Distinct().ToList();

foreach (var countyName in counties)
{
CountyFilter county = new CountyFilter();
county.County = countyName;
county.IsChecked = true;
countyFilters.Add(county);
}

db.CountyFilters.AddRange(countyFilters);
db.SaveChanges();
}

private void ResetGenders()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [GenderFilter]");
db = new digital_datahouse_bulk_mailerEntities();

List<GenderFilter> genderFilters = new List<GenderFilter>();

var genders = (
from c in db.Contacts
select c.Gender

).Distinct().ToList();

foreach (var genderName in genders)
{
GenderFilter gender = new GenderFilter();
gender.Gender = genderName;
gender.IsChecked = true;
genderFilters.Add(gender);
}

db.GenderFilters.AddRange(genderFilters);
db.SaveChanges();
}

private void ResetIndustries()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [IndustryFilter]");
db = new digital_datahouse_bulk_mailerEntities();

List<IndustryFilter> industryFilters = new List<IndustryFilter>();

var industries = (
from c in db.Contacts
select c.Industry

).Distinct().ToList();

foreach (var industryName in industries)
{
IndustryFilter industry = new IndustryFilter();
industry.Industry = industryName;
industry.IsChecked = true;
industryFilters.Add(industry);
}

db.IndustryFilters.AddRange(industryFilters);
db.SaveChanges();
}

private void ResetIsContactedFilters()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [IsContactedFilter]");
db = new digital_datahouse_bulk_mailerEntities();

List<IsContactedFilter> isContactedFilters = new List<IsContactedFilter>();

var isContacted = (
from c in db.Contacts
select c.IsContacted

).Distinct().ToList();

foreach (var contactedName in isContacted)
{
IsContactedFilter contacted = new IsContactedFilter();
contacted.IsContacted = contactedName;
contacted.IsChecked = true;
isContactedFilters.Add(contacted);
}

db.IsContactedFilters.AddRange(isContactedFilters);
db.SaveChanges();
}

private void ResetSicFilters()
{
db.Database.ExecuteSqlCommand("TRUNCATE TABLE [SicCodeDescriptionFilter]");
db = new digital_datahouse_bulk_mailerEntities();

List<SicCodeDescriptionFilter> sicFilters = new List<SicCodeDescriptionFilter>();

var sics = (
from c in db.Contacts
select c.SIC_Code_Description

).Distinct().ToList();

foreach (var sic in sics)
{
SicCodeDescriptionFilter sicCode = new SicCodeDescriptionFilter();
sicCode.SicCodeDescription = sic;
sicCode.IsChecked = true;
sicFilters.Add(sicCode);
}

db.SicCodeDescriptionFilters.AddRange(sicFilters);
db.SaveChanges();
}

public void UpdateIsContactedInformation(Contact contact)
{
db = new digital_datahouse_bulk_mailerEntities();

contact.IsContacted = "True";
contact.MessageDateSent = DateTime.Today;

db.Contacts.AddOrUpdate(contact);
db.SaveChanges();
}
}
}

这是使用 ViewModel 的 View ,称为 ContactsView - 此 View 与其他 View 一样包含在 MainWindow 中

联系人 View :

<UserControl x:Class="Digital_Data_House_Bulk_Mailer.View.ContactsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Digital_Data_House_Bulk_Mailer.View"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:model="clr-namespace:Digital_Data_House_Bulk_Mailer.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<model:ContactsViewModel/>
</UserControl.DataContext>
<Grid Margin="0,0,-690,-36" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="61*"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding DeleteCommand}" Controls:TextBoxHelper.ClearTextButton="True" x:Name="delete" Content="DELETE" HorizontalAlignment="Left" Margin="115,21,0,0" VerticalAlignment="Top" Width="100" RenderTransformOrigin="0.267,0.519"/>
<Button Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding UpdateCommand}" Controls:TextBoxHelper.ClearTextButton="True" x:Name="update" Content="add / update" HorizontalAlignment="Left" Margin="10,21,0,0" VerticalAlignment="Top" Width="100" RenderTransformOrigin="0.267,0.519"/>
<Button Style="{StaticResource AccentedSquareButtonStyle}" Controls:TextBoxHelper.ClearTextButton="True" x:Name="bulk_import" Content="import new data" HorizontalAlignment="Left" Margin="220,21,0,0" VerticalAlignment="Top" Width="110" RenderTransformOrigin="0.267,0.519" Click="bulk_import_Click"/>
<DataGrid SelectedItem="{Binding Contact}" AutoGenerateColumns="True" ItemsSource="{Binding Path=Contacts, Mode=TwoWay}" Style="{StaticResource AzureDataGrid}" x:Name="dataGridCodeBehind" Margin="10,54,521,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ColumnWidth="*">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="FontSize" Value="10"/>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
<Button IsEnabled="{Binding IsRefreshEnabled}" Style="{StaticResource AccentedSquareButtonStyle}" Command="{Binding LoadCommand}" x:Name="refreshData" Content="Refresh Contacts" HorizontalAlignment="Left" Height="22" Margin="335,21,0,0" VerticalAlignment="Top" Width="114"/>
<Controls:ProgressRing IsActive="{Binding IsRefreshProgressActive}" Foreground="{DynamicResource AccentColorBrush}" Margin="720,0,0,0" RenderTransformOrigin="-2.889,0.463" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="50"/>
<Button x:Name="deleteContacts" Command="{Binding DeleteAllContactsCommand}" Style="{StaticResource AccentedSquareButtonStyle}" Content="Delete All Contacts" HorizontalAlignment="Left" Height="22" Margin="454,21,0,0" VerticalAlignment="Top" Width="114"/>
<Button x:Name="recreateFilters" Command="{Binding RecreateFiltersCommand}" Content="Recreate TO MAIL Filters" HorizontalAlignment="Left" Style="{StaticResource AccentedSquareButtonStyle}" Height="22" Margin="573,21,0,0" VerticalAlignment="Top" Width="142"/>

</Grid>

非常糟糕的是,当我尝试调试时,它甚至没有转到代码 - 方法调用。还尝试使用一些分析工具,但我没有得出任何结论是什么导致了这个卡住问题......

当我从数据库编辑器对数据库运行查询时,我立即得到了结果。

我还在使用 ReportViewer 显示的应用程序中使用 SSRS 报告 - 它也可以正常工作并返回相同的数据 - 它显示在单独的 View 中。

在其中一个 View 中,我使用 WpfAnimatedGif 库显示了一个 GIF 动画 - 我试图删除此引用以查看这是否会导致问题,但它不会继续卡住...

我还尝试重写我的存储库类以使用 using 命令为每个方法创建新的 db 实例,但这不是问题所在。

解决方案文件: Google Disk Solution Link

最佳答案

我终于解决了这个问题。我需要的是将 Height="500"属性添加到数据网格。

在我的例子中,当显示超过 50 行时,删除 Height 属性会使 DataGrid 卡住。通过添加高度,它可以在不到一秒的时间内加载 5000 条记录。

关于c# - Wpf 应用程序卡住 - 大量内存泄漏之谜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50423381/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com