從學習c#到現在,我編的程式都是執行的非常快的,然而今天用listview模擬檔案瀏覽界面,點擊按鈕加載存盤在陣列或集合里的檔案地址,最后用了10秒左右的時間才在listview控制元件內顯示,為什么會這樣啊?這個該怎么解決啊,甚至有時運行時拋出
“這種狀態已持續 60 秒。擁有目標背景關系/單元的執行緒很有可能執行的是非泵式等待或者在不發送 Windows 訊息的情況下處理一個運行時間非常長的操作。這種情況通常會影響到性能,甚至可能導致應用程式不回應或者使用的記憶體隨時間不斷累積。要避免此問題,所有單執行緒單元(STA)執行緒都應使用泵式等待基元(如 CoWaitForMultipleHandles),并在運行時間很長的操作程序中定期發送訊息。”的例外
為什么大部分檔案瀏覽軟體,點擊一個檔案夾節點,就一下就加載完了?難道是用了快取?我是剛學wpf不就得新人,想模擬檔案瀏覽界面,編譯結果慢的超過10秒以上,有什么解決辦法么,優化?有沒有加快執行速度的代碼?或者搞分頁?或者用異步編程加載么(執行緒我還沒學,若學習時間完成短的話可以考慮下),可以說下用哪種方式是比較好的了,分頁、加快執行速度的代碼、異步編程加載或者其他的方法(最好不升級電腦配置)。
代碼段
//點擊該按鈕加載一次性加載大量listviewitem節點,這些節點對應一個圖片
private void button_Click_1(object sender, RoutedEventArgs e)
{
DirectoryInfo TheFolder = new DirectoryInfo(@"E:\圖片\風景");
string a=DateTime.Now.ToString();
foreach (FileInfo NextFile in TheFolder.GetFiles())
{
if (System.IO.Path.GetExtension(NextFile.FullName) == ".bmp"|| System.IO.Path.GetExtension(NextFile.FullName)==".jpg"
||System.IO.Path.GetExtension(NextFile.FullName) == ".png")
{
ListViewItem b = new ListViewItem();
b.Width = 120;
Thickness thick = new Thickness(10);
b.Margin = thick;
listview1.Items.Add(b);
StackPanel sp = new StackPanel();
b.Content = sp;
sp.HorizontalAlignment =HorizontalAlignment.Center;
sp.VerticalAlignment = VerticalAlignment.Center;
Image ig = new Image();
ig.Source = new BitmapImage(new Uri(NextFile.FullName));
ig.Stretch = Stretch.Uniform;
ig.Height = 90;
TextBlock tb = new TextBlock();
tb.Text = System.IO.Path.GetFileNameWithoutExtension(NextFile.Name);
tb.Height = 50;
sp.Children.Add(ig);
sp.Children.Add(tb);
}
}
}
uj5u.com熱心網友回復:
listbox和listview都不是適合呈現大量資料的控制元件,幾乎沒有優化,可以進行分頁,或者使用GridView,重寫模板,比listview更容易控制uj5u.com熱心網友回復:
分頁uj5u.com熱心網友回復:
延遲加載,可以就像手機刷微博一樣,先加載一部分,等往下拖的時候再加載一部分。或者在底部增加一個"加載更多"的按鈕,點擊加載更多內容。這樣的方法估計你的代碼改動會相對比較小。uj5u.com熱心網友回復:
,那請問有沒有源代碼么?或者應該怎么寫?我沒用過gridview或者可以通過釋放垃圾,清空記憶體的方式解決么?uj5u.com熱心網友回復:
是因為一直add沒有clear嗎?uj5u.com熱心網友回復:
最難受的就是看見你們以winform的方式寫WPF 資料系結他不香嗎 為什么你們老覺得WPF慢 你得去深入的理解啊首先是xaml代碼:
<Grid>
<ListView x:Name="LvwTest">
<ListView.ItemTemplate>
<ItemContainerTemplate>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Image Stretch="Uniform" Height="90" Source="{Binding ImgSource}"/>
<TextBlock Text="{Binding FileName}" Height="50"/>
</StackPanel>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
在是后端代碼:
public partial class MainWindow : Window
{
private ObservableCollection<ImgInfo> ImgInfos = new ObservableCollection<ImgInfo>();
public MainWindow()
{
InitializeComponent();
LvwTest.ItemsSource = ImgInfos;
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if(e.Key==Key.Left)
{
ImgInfos.Clear();
var files = System.IO.Directory.GetFiles("D:/圖片");
foreach (var file in files)
{
ImgInfos.Add(new ImgInfo()
{
FileName = System.IO.Path.GetFileNameWithoutExtension(file)
,
ImgSource = new BitmapImage(new Uri(file))
});
}
}
if(e.Key==Key.Right)
{
ImgInfos.Clear();
}
}
}
public class ImgInfo
{
public BitmapImage ImgSource { get; set; }
public string FileName { get; set; }
}
最后是運行結果 左鍵添加 右鍵清空 簡簡單單一百行代碼都不到 效率卻能提高很多倍:
uj5u.com熱心網友回復:
如果你覺得會卡 還可以將集合添加那塊換成異步委托,這樣的話 起碼界面不會像你說的那樣卡住:foreach (var file in files)
{
Dispatcher.BeginInvoke(()=> ImgInfos.Add(new ImgInfo()
{
FileName = System.IO.Path.GetFileNameWithoutExtension(file)
,
ImgSource = new BitmapImage(new Uri(file))
}));
}
注意參考命名空間:
using System.Windows.Threading;
uj5u.com熱心網友回復:
還有篩選檔案那一塊 不要多次使用IO操作 性能非常底下 直接通過判斷字串來篩選就行了 舉個例子:
var files = System.IO.Directory.GetFiles("D:/圖片");
files = files.Where(s => s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) |
s.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) |
s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase)).ToArray();
后面的StringComparison是忽略大小寫 你可能會遇到大寫后綴名 或者大小寫夾雜的后綴名 如果出現這種清空 你的程式就出現了bug了
uj5u.com熱心網友回復:
補充一個小知識,不推薦使用 BeginInvoke 方法,請用 InvokeAsync 方法[深入了解 WPF Dispatcher 的作業原理(Invoke/InvokeAsync 部分) - walterlv](https://blog.walterlv.com/post/dotnet/2017/09/26/dispatcher-invoke-async.html )
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/64942.html
標籤:C#
上一篇:c# 控制元件完全透明
