Answer the question
In order to leave comments, you need to log in
How to properly inform about the progress of the task?
Good afternoon. How to correctly and beautifully notify about the progress of the task? For example notify progressbar and display message on textbox on winforms?
For example, such a class
class WorkClass
{
public async Task LongMethod(List<string> somethink)
{
await Task.Factory.StartNew(() =>
{
//отсюда делать вывод somethink.Count()
foreach (string element in somethink)
{
Thread.Sleep(5000);
//тут делать вывод о выполнении
}
});
}
}
Answer the question
In order to leave comments, you need to log in
I tried using the Progress class, but here I did not like to produce a large number of classes through
Progress.Report(new MyReport{...});
public interface IProgressInfo
{
bool IsCompleted { get; }
}
public class ProgressInfo : IProgressInfo
{
public ProgressInfo(double completedPercentage, string progressStatusText)
{
CompletedPercentage = completedPercentage;
ProgressStatusText = progressStatusText;
}
public double CompletedPercentage { get; private set; }
public string ProgressStatusText { get; private set; }
public bool IsCompleted
{
get { return CompletedPercentage >= 1; }
}
}
public class Progress<T> : IProgress<T> where T : class, IProgressInfo
{
private T _previousProgressInfo;
private volatile T _progressInfo;
private readonly Action<T> _updateProgressAction;
private readonly Timer _timer;
private readonly SynchronizationContext _synchronizationContext;
public Progress(TimeSpan pollingInterval, Action<T> updateProgressAction)
{
_synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
_updateProgressAction = updateProgressAction;
_timer = new Timer(TimerCallback, null, pollingInterval, pollingInterval);
}
private void TimerCallback(object state)
{
ProcessUpdate();
}
private void ProcessUpdate()
{
var progressInfo = _progressInfo;
if (_previousProgressInfo != progressInfo)
{
_synchronizationContext.Send(state => _updateProgressAction((T) state), progressInfo);
}
_previousProgressInfo = progressInfo;
}
public void Report(T value)
{
_progressInfo = value;
if (value.IsCompleted)
{
_timer.Dispose();
ProcessUpdate();
}
}
}
var workClass = new WorkClass();
var list = Enumerable.Range(1, 1000).Select(i => i.ToString()).ToArray();
var progress = new Progress<ProgressInfo>(TimeSpan.FromMilliseconds(100), UpdateProgressAction);
await workClass.LongMethod(list, progress);
private void UpdateProgressAction(ProgressInfo obj)
{
ProgressBar.Value = obj.CompletedPercentage;
OperationStatus.Text = obj.ProgressStatusText;
ProgressBarPercentage.Text = string.Format("{0:P}", obj.CompletedPercentage);
}
internal class WorkClass
{
public async Task LongMethod(IReadOnlyList<string> something, IProgress<ProgressInfo> progress)
{
await Task.Factory.StartNew(() =>
{
var count = something.Count;
for (int i = 0; i < count; i++)
{
var element = something[i];
Thread.Sleep(5);
progress.Report(new ProgressInfo((double)(i + 1) / count, element));
}
});
}
}
Practical guide. Executing an operation in the background
To perform a long-running task, you need to use a BackgroundWorker .
In the DoWork event, describe your long-term work.
As you work (in the DoWork handler), you call the ReportProgress method to inform the main program about the progress of the processing. The ProgressChanged event comes to the main program.
Periodically monitor if anyone is trying to stop your work through CancellationPending.
To start a job, use the RunWorkerAsync method. Through the ProgressChanged event, track progress and update the progress bar. On the RunWorkerCompleted event, you learn about the completion or interruption of work.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question