PDA

View Full Version : محاسبه هزینه Load فرم و نمایش یک ProgressBar بر اساس این هزینه



PetekDincos
یک شنبه 24 بهمن 1389, 15:43 عصر
با سلام
بعضی از فرم ها ممکن است هزینه (زمان) لود شون به خاطر محاسبات زیاد یا حجم زیاد داده یا گرافیک بالا و غیره زیاد باشه من می خواستم برای اینکه بتوان این هزینه رو محاسبه کرد و بر اساس این هزینه یک ProgressBar تا قیل از لود کامل صفحه نشون داد من رو راهنمایی کنید با تشکر

مهدی فرزاد
دوشنبه 25 بهمن 1389, 10:21 صبح
سلام
برای این کار شما باید از BackgroundWorker استفاده کنید و زمان اون عملی رو که باعث تاخیر در لود شدن فرمتون میشه رو بدست بیارید
من یک مثال ساده آماده کردم امیدوارم کمکتون کنه

برای مثال
من دو فرم درست کردم که یکی با BackgroundWorker کار میکنه و دیگری بدونه BackgroundWorker

در هر دوفرم من یک متد دارم به شکل زیر

int j;
privatevoid Up_J_Value()
{
do
{
j++;
System.Threading.Thread.Sleep(50);

} while (j != 100);
}
که مقدار متغییر j رو به تدریج و با تخیر افزاریش میده

در فرم اول این متد در اینجا صدا زده میشه

public Window1()
{
InitializeComponent();
Up_J_Value();
}
این عمل مشابه خواندن اطلاعات از دیتابیس و پرشدن آبجکت مورد نظر هست که زمان بر میباشد
و در Loaded فرم هم لست باکس با این کد پر میشه
privatevoid Window_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < j; i++)
{
listBox1.Items.Add(i);
}
}
خوب کاملا مشخصه که فرم با تخیر باز میشه

حالا همین کار رو در فرم دوم با استفاده از BackgrandWorker انجام میدیم
به شکل زیر

در کد Xaml این ها رو مینویسیم

xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"
<Window.Resources>
<cm:BackgroundWorker x:Key="Worker" DoWork="BackgroundWorker_DoWork"
RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted"
WorkerReportsProgress="True"
ProgressChanged="BackgroundWorker_ProgressChanged" />

</Window.Resources>

بعد با این کد BackgroundWorker رو در کد C# معرفی میکینم

public Window2()
{
InitializeComponent();
worker = (BackgroundWorker)FindResource("Worker");
}

حالا Event های اونو به شکل زیر مینویسم

privatevoid Window_Loaded(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync();
}
privatevoid BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Up_J_Value();

}
privatevoid BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
for (int i = 0; i < j; i++)
{
listBox1.Items.Add(i);
}
}
privatevoid BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}

دقت کنید پر شدن j رو در Event مربوط به BackgroundWorker_DoWork نوشتیم نه در ابتدای برنامه

و این قطعه کد قرمز رو به متدد اضافه کردیم

int j;
privatevoid Up_J_Value()
{
do
{
j++;
System.Threading.Thread.Sleep(50);
worker.ReportProgress(j);//قرمز//
} while (j != 100);
}

حالا در فرم لود بجای حالت قبل مینویسیم

privatevoid Window_Loaded(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync();
}

نتیجه رو ببینید

اگر دقت کنید ما مقدار افزار j رو به عنوان ReportProgress معرفی کردیم

من ساده ترین حالت ممکن بود حالتهای پیچیده تری وجود داره که سرچ کنید در گوگل حتما پیدا خواهید کرد
جایی خوندم گفته بود مثلا شما میتونید این مقدار رو برای دیتا بیس از روی مقدار Count لود دشه از دیتا بیس بدست بیارید یا مثلا در لود شدن یک عکس از میزان حجم فابل خونده شده
من به شخصه کار نکردم در همین حد تونستم اگه کمکی باشه کمک کنم

این Pdf رو ببینید http://www.jeremybytes.com/Downloads/BackgroundWorkerInWPF.pdf

در لینک مقابل هم یک بحث در مرود لودشدن از دیتابیس گفته شده ببینید شاید نتیجش مورد استفاده شما باشه http://stackoverflow.com/questions/4467569/backgroundworker-slow

این هم در خصوص لود شدن Image بحث کرده http://www.codeproject.com/Questions/58355/Loading-Image-With-BackgroundWorker.aspx