Chcę pokazać postęp obliczeń, które wykonuję w zewnętrznej bibliotece.
Na przykład, jeśli mam jakąś metodę obliczeniową i chcę jej użyć dla 100000 wartości w mojej klasie Form, mogę napisać:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Caluculate(int i)
{
double pow = Math.Pow(i, i);
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Maximum = 100000;
progressBar1.Step = 1;
for(int j = 0; j < 100000; j++)
{
Caluculate(j);
progressBar1.PerformStep();
}
}
}
Po każdym obliczeniu powinienem wykonać krok. Ale co jeśli wykonam wszystkie 100000 obliczeń metodą zewnętrzną. Kiedy powinienem „wykonać krok”, jeśli nie chcę uzależniać tej metody od paska postępu? Mogę na przykład pisać
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void CaluculateAll(System.Windows.Forms.ProgressBar progressBar)
{
progressBar.Maximum = 100000;
progressBar.Step = 1;
for(int j = 0; j < 100000; j++)
{
double pow = Math.Pow(j, j); //Calculation
progressBar.PerformStep();
}
}
private void button1_Click(object sender, EventArgs e)
{
CaluculateAll(progressBar1);
}
}
ale nie chcę tego robić.
c#
winforms
progress-bar
Dmytro
źródło
źródło
Odpowiedzi:
Proponuję przyjrzeć się BackgroundWorker . Jeśli masz tak dużą pętlę w swoim WinForm, zostanie ona zablokowana, a aplikacja będzie wyglądać tak, jakby się zawiesiła.
Zobacz,
BackgroundWorker.ReportProgress()
jak zgłosić postęp z powrotem do wątku interfejsu użytkownika.Na przykład:
źródło
BackgroundWorker
jest dodawany przez projektanta i tam konfigurowany. Ale tak, należy go skonfigurować, aby byłWorkerReportsProgress
ustawiony natrue
.RunWorkerCompleted
obsługi zdarzeń, jeśli twójDoWork
handler tego nie robi ..Od .NET 4.5 możesz używać kombinacji async i czekać z Progress na wysyłanie aktualizacji do wątku interfejsu użytkownika:
Zadania są obecnie preferowanym sposobem realizacji tego, co
BackgroundWorker
robi.źródło
await DoWorkAsync(progress);
? Jest to bardzo celowe, ponieważ nie spowodowałoby uruchomienia dodatkowego wątku. Funkcja byłaby kontynuowana tylko w przypadkuDoWorkAsync
wywołania własnego,await
np. Oczekiwania na operację we / wybutton1_Click
. Główny wątek interfejsu użytkownika jest zablokowany na ten czas. JeśliDoWorkAsync
nie jest tak naprawdę asynchroniczny, ale tylko wiele instrukcji synchronicznych, nic nie zyskujesz.Step
jest dostępny tylko na pasku postępu WinForms i nie jest tu potrzebny, ale był obecny w przykładowym kodzie pytania (otagowany winforms), więc może zostać.Hej, jest przydatny samouczek na temat pereł Dot Net: http://www.dotnetperls.com/progressbar
W porozumieniu z Peterem, musisz użyć pewnej ilości wątków, w przeciwnym razie program po prostu się zawiesi, co nieco zniweczy cel.
Przykład wykorzystujący ProgressBar i BackgroundWorker: C #
źródło
Jest
Task
, jest niecelowyBackgroundWorker
,Task
jest prostszy. na przykład:ProgressDialog.cs:
Gotowe! Następnie możesz ponownie użyć ProgressDialog w dowolnym miejscu:
źródło