Answer the question
In order to leave comments, you need to log in
How to bind ProgressBar in C# (Windows Forms) to a specific method?
Good day!
I am writing a WinForms application in C#. This is a solution from several projects. In one project, the visual part is collected, so to speak, and the main actions are performed in another. The first project has a form with a button to launch a long-running process from the second project. Is it possible somehow to bind the ProgressBar on the form in the first project to the execution of this long-running process from the second one?
This is how the structure of the solution looks like.
The first project is the form itself.
using Project2;
namespace Project1
{
public partial class frmRun : Form
{
LongRunningTaskPerformer _ltp;
//...
private void btnRun_Click(object sender, EventArgs e)
{
_ltp = new LongRunningTask();
_ltp.Run();
}
}
}
The second project is a long-running process, to which you need to attach a ProgressBar.
namespace Project2
{
public class LongRunningTaskPerformer
{
//...
public void Run()
{
DoStep1();
DoStep2();
DoStep3();
}
private void DoStep1()
{
Thread.Sleep(10000);// there might be something else here
}
private void DoStep2()
{
Thread.Sleep(10000);//something else here
}
private void DoStep3()
{
Thread.Sleep(10000);//something else here
}
}
}
Answer the question
In order to leave comments, you need to log in
When creating a LongRunningTaskPerformer, pass it a dependency on something like
public interface INotifyProgress
{
void Notify(int percent);
}
ush , thanks! Earned.
For those who are interested, here is the code:
DLL with a long-running process (LongRunningTask):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;//чисто для задержки потоков, т.е. для симуляции долгоиграющего процесса
namespace LongRunningTask
{
public class LongRunningTaskPerformer
{
//Интерфейс оповещения, реализуемый клиентом, которому интересно состояние долгоиграющего процесса.
//В нашем случае это форма запуска.
private readonly INotifyProgress _notifier;
public LongRunningTaskPerformer(INotifyProgress notifier)
{
if (notifier != null)
{
_notifier = notifier;
}
}
public void Run()
{
//После каждого шага вызываем метод-оповещатель Notify. В случае с формой в реализации этого метода будет обновление прогресс-бара.
DoStep1();
_notifier.Notify(33);
DoStep2();
_notifier.Notify(66);
DoStep3();
_notifier.Notify(100);
}
private void DoStep1()
{
Debug.WriteLine("Step 1");
Thread.Sleep(12000);
Debug.WriteLine("Step 1 completed!");
}
private void DoStep2()
{
Debug.WriteLine("Step 2");
Thread.Sleep(12000);
Debug.WriteLine("Step 2 completed!");
}
private void DoStep3()
{
Debug.WriteLine("Step 3");
Thread.Sleep(12000);
Debug.WriteLine("Step 3 completed! Work done.");
}
}
}
namespace LongRunningTask
{
public interface INotifyProgress
{
void Notify(int percent);
}
}
namespace MyProgressBar
{
//Наша форма запуска реализует интерфейс оповещения INotifyProgress. Это надо, чтобы форма смогла получать данные о состоянии долгоиграющего процесса
//ПО МЕРЕ его выполнения. Без реализации интерфейса ничего работать не будет!
public partial class frmProgressBar : Form, INotifyProgress
{
//Класс, выполняющий наш долгоиграющий процесс
LongRunningTaskPerformer _ltp;
//Делегат, воспроизводящий внешний вид метода-оповещателя из интерфейса INotifyProgress.
//Он нужен для обеспечения потокобезопасной передачи данных в форму. Если его не будет, программа вылетит
//с исключением типа "обращение к progressBar не из его потока" (или что-то подобное).
delegate void NotifyCallback(int value);
public frmProgressBar()
{
InitializeComponent();
}
//Сам процесс запускается с помощью backgroundWorker-а. Кнопка Run только запускает этот backgroundWorker.
private void btnRun_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Выполнение долгоиграющего процесса.
_ltp = new LongRunningTaskPerformer(this);
_ltp.Run();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Как-то показываем, что у нас завершился наш долгоиграющий процесс и возвращаем прогресс-бар в исходное состояние.
MessageBox.Show("Process completed!");
progressBar1.Value = 0;
}
//Реализация процедуры оповещения о состоянии долгоиграющего процесса.
public void Notify(int percent)
{
//Чтобы передача состояния процесса сработала корректно и программа не вылетела,
//надо делать в точности как здесь (за подробностями - MSDN:
//http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28EHInvalidOperation.WinForms.IllegalCrossThreadCall%29;k%28TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5%29;k%28DevLang-csharp%29&rd=true)
if (progressBar1.InvokeRequired)
{
NotifyCallback d = new NotifyCallback(Notify);
this.Invoke(d, new object[] { percent });
}
else
{
progressBar1.Value = percent;
}
}
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question