Обновление прогресбара из другого потока
Задача обновить прогресбар из другого потока, из метода объекта. В целом ошибок не возникает, но ничего не происходит.
Методы для обновления прогресбаров (Файл Form1
, методы объекта класса App
):
public void set_pb_images(int images_count, App core, int images_done = 0)
{
MethodInvoker mi = new MethodInvoker(() => pbImages.Value = (int)Math.Round((decimal)images_done / (decimal)images_count));
if (pbImages.InvokeRequired)
{
pbImages.Invoke(mi);
}
else
{
mi.Invoke();
}
}
public void set_pb_current(int objects_count, App core, int objects_done = 0)
{
MethodInvoker mi = new MethodInvoker(() => pbCurrentImage.Value = (int)Math.Round((decimal)objects_done / (decimal)objects_count));
if (pbCurrentImage.InvokeRequired)
{
pbCurrentImage.Invoke(mi);
}
else
{
mi.Invoke();
}
}
Откуда вызываются методы (Файл Image_prepare
, метод объекта класса Image_prepare
):
public string prepare()
{
App local_app = new App();
// какой-то функционал
int all_objs = objects.shapes.Count * 2 + 5;
int done_objs = 0;
// какой-то функционал
local_app.set_pb_current(all_objs, local_app, done_objs);
// какой-то функционал
local_app.set_pb_current(all_objs, local_app, done_objs);
// какой-то функционал
for (int index = 0; index < list.Length; index++)
{
// какой-то функционал
local_app.set_pb_current(all_objs, local_app, done_objs);
}
for (int obj_index = 0; obj_index < list.Length; obj_index++)
{
// какой-то функционал
local_app.set_pb_current(all_objs, local_app, done_objs);
}
// какой-то функционал
}
Запуск потока на обработку изображения (Файл Form1
):
public partial class App : Form
{
private Thread _thread = null;
// какие-то данные
public App(bool init = true)
{
Form app = ActiveForm;;
if (init) InitializeComponent();
}
public void set_pb_images(int images_count, App core, int images_done = 0)
{
MethodInvoker mi = new MethodInvoker(() => pbImages.Value = (int)Math.Round((decimal)images_done / (decimal)images_count));
if (pbImages.InvokeRequired)
{
pbImages.Invoke(mi);
}
else
{
mi.Invoke();
}
}
public void set_pb_current(int objects_count, App core, int objects_done = 0)
{
MethodInvoker mi = new MethodInvoker(() => pbCurrentImage.Value = (int)Math.Round((decimal)objects_done / (decimal)objects_count));
if (pbCurrentImage.InvokeRequired)
{
pbCurrentImage.Invoke(mi);
}
else
{
mi.Invoke();
}
}
private void RunOnUiThread(Action action) // пробовал - ошибка
{
if (InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
public bool local_start_point(string path) // создание потока на обработку изображения
{
if (_thread == null)
{
_thread = new Thread(() => prepare_raw(path));
_thread.IsBackground = true;
_thread.Start();
return true;
}
else
{
Console.WriteLine("Idk dfkb;kdfbjdfkgdgpk");
return false;
}
}
private void prepare_raw(string path)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Settings settings = get_raw_settings();
settings.path = path;
//set_pb_current(1);
string output = new Image_prepare(settings).prepare();
// Call saveFileDialog for output
RunOnUiThread(() =>
{
// сохранение файла
});
if (_thread != null) _thread.Abort();
}
private void click_run(object sender, EventArgs e)
{
if (!file_opened) return;
local_start_point(file_path);
}
}
Ответы (1 шт):
Решение оказалось немного спецефичным. Так как точка запуска программы находится в Program.cs
, можно сделать метод который будет задавать в Form1.cs
перменную public App local_app = null;
по средству this
.
public static class Program
{
[STAThread]
static void Main()
{
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new App().set_local_app());
}
}
// метод set_local_app()
public App set_local_app()
{
local_app = this;
return this;
}
Дальше local_app
можно использовать для обработки почти любого элемента на других потоках, если передать ее как аргумент для метода/функции.