ProgressBar בWPF תוך כדי פעולת thread
-
יש לי קוד בc# שקורא כמות של קבצים בבת אחת (בעצם תוכנת חיפוש פשוטה שאמורה לשמש את מי שאין לו מקום במחשב בשביל אינדקס) וכדי למהר את הפעולה אני משמתמש בThreading
נתקלתי בבעיה שאני לא מצליח לעדכן את הprogressbar תוך כדי פעולת הthreading כדי להראות התקדמות. (בwinforms הצלחתי על ידי invoke).
ניסיתי על ידי Dipatcher ללא הועיל.
ניסיתי על ידי Binding ללא הועיל.בעצם מה שקורה שאם אני עושה פעולת דמע
Thread.Sleep(100); // Simulating some work being done
אז הכל טוב
אבל ברגע שאני מתחיל לקרוא קבצים שום כלום.
מצו"ב הקוד שלי של הbinding אשמח לקבל עזרה<Window x:Class="WPF_BInding.ProgressBarBinding" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPF_BInding" mc:Ignorable="d" Title="ProgressBarBinding" Height="450" Width="800"> <Grid> <StackPanel> <ProgressBar Height="25" Name="progressBar" Minimum="0" Maximum="100" Value="{Binding PercentDone}" /> <Button Content="Start Task" HorizontalAlignment="Center" VerticalAlignment="Bottom" Click="StartTask_Click" /> </StackPanel> </Grid> </Window>
public partial class ProgressBarBinding : Window, INotifyPropertyChanged { private int _percentDone; private int _progressBarMaximum = 100; public int PercentDone { get { return _percentDone; } set { if (_percentDone != value) { _percentDone = value; OnPropertyChanged(nameof(PercentDone)); } } } public int ProgressBarMaximum { get { return _progressBarMaximum; } set { if (_progressBarMaximum != value) { _progressBarMaximum = value; OnPropertyChanged(nameof(ProgressBarMaximum)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public ProgressBarBinding() { InitializeComponent(); DataContext = this; // Set the data context to the MainWindow itself progressBar.Maximum = ProgressBarMaximum; // Set the initial Maximum value }
-
@pcinfogmach כתב בProgressBar בWPF תוך כדי פעולת thread:
ניסיתי על ידי Dipatcher ללא הועיל.
ניסיתי על ידי Binding ללא הועיל.Binding לא משנה פה, Dispacher עשוי בשביל זה אבל על האופן הזה לא הבאת קוד שנבין למה לך זה לא עובד.
-
private async void search(string[] files) { progressBar.Maximum = files.Length; List<System.Threading.Tasks.Task> searchTasks = new List<System.Threading.Tasks.Task>(); foreach (string file in files) { searchTasks.Add(Task.Run(() => { this.Dispatcher.Invoke(() => { progressBar.Value = progressBar.Value + 1; File.ReadAllLines(file); }); })); } await System.Threading.Tasks.Task.WhenAll(searchTasks); progressBar.Value = 0; }
-
-
@dovid
לא הבנתי כלום. אני מודה באשמה הניסיון שלי בbinding היה ניסוי וטעיה (אני עוד לא מבין את המושג מספיק). אבל הקוד של ה-Invoke לא נתפס אצלי כניסוי וטעיה - אולי הוא טעות אבל לא ניסוי וטעיה.הנה איך שאני מבין את הקוד - תסביר לי היכן אני טועה או פשוט לא מבין כלום:
- הקוד יוצר רשימה של משימות
- הוא מבצע אותם בצורה של threading
- כל משימה מכילה בתוכ פקודה של עדכון ה-progressbar (שזה לא קורה!)
- לאחר סיום כל המשימות ה-progressbar מאופס כדי שיהי מוכן לחיפוש הבא.
נ.ב. גם אשמח אם תסביר לי למה בwinforms בדיוק אותו הדבר עובד מצויין. (רק ששם אני יכול להשתמש עם invoke בלי dispatcher).
-
@dovid כתב בProgressBar בWPF תוך כדי פעולת thread:
ספציפית לבעיה הזאת מן הסתם גוגל על task dispatcher progressbar יעזור לך,
אני לא עצלן כבר עשיתי את גוגל לפני שפתחתי פוסט. הבעיה נפוצה הפתרונות... או שלא לא מבין אותם או שהם ממש לא קשורים.
אשמח מאוד אם מישהו ירחם עלי ויסביר לי מה הפתרון.
-
@pcinfogmach כתב בProgressBar בWPF תוך כדי פעולת thread:
private async void search(string[] files) { progressBar.Maximum = files.Length; List<System.Threading.Tasks.Task> searchTasks = new List<System.Threading.Tasks.Task>(); foreach (string file in files) { searchTasks.Add(Task.Run(() => { this.Dispatcher.Invoke(() => { progressBar.Value = progressBar.Value + 1; File.ReadAllLines(file); }); })); } await System.Threading.Tasks.Task.WhenAll(searchTasks); progressBar.Value = 0; }
למה
File.ReadAllLines(file)
נמצא בתוך הקריאה לDispatcher.Invoke
? תנסה להוציא אותו מחוץ ל Dispatcher, הקריאה אמורה להכיל קוד שמשנה את התצוגה בלבד. הגיוני שהתרד של התצוגה נתקע כי את מריץ עליו עוד לוגיקה שלא קשורה ל UI שיתכן שגוזלת זמן, ובגלל שה UI לא מגיב אתה לא רואה את ההתקדמות. (חוץ מזה שצריך לאפס אתprogressBar.Value
לאפס, מה ש @dovid כתב לך)