#c# #wpf #multithreading #progress-bar
#c# #wpf #многопоточность #индикатор выполнения
Вопрос:
Я открываю новое окно в отдельном потоке. Я хочу, чтобы окно открылось и задание запустилось автоматически, затем сообщить о его ходе в этом окне (я буду использовать индикатор выполнения).
Код действия, который открывает окно :
private void button_Run_Click(object sender, RoutedEventArgs e)
{
ExecutorWindow myExecWindow = new ExecutorWindow();
myExecWindow.Show();
}
Код окна :
public partial class ExecutorWindow : Window
{
BackgroundWorker execBackground = new BackgroundWorker();
public ExecutorWindow()
{
InitializeComponent();
RunExecutor();
}
public void RunExecutor()
{
// CREATE BACKGROUNDWORKER FOR EXECUTOR
execBackground.DoWork = new DoWorkEventHandler(execBackground_DoWork);
execBackground.RunWorkerCompleted = new RunWorkerCompletedEventHandler(execBackground_RunWorkerCompleted);
execBackground.WorkerReportsProgress = true;
execBackground.WorkerSupportsCancellation = true;
// RUN BACKGROUNDWORKER
execBackground.RunWorkerAsync();
}
private void execBackground_DoWork(object sender, DoWorkEventArgs e)
{
// CREATE EXECUTOR INSTANCE
Executor myExecutor = new Executor(arg1, arg2);
myExecutor.RunWhileRemainMachines();
}
private void execBackground_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("RunWorkerCompleted execBackground");
}
}
Но что происходит, так это то, что RunProcessingJob вызывается только тогда, когда я закрываю окно (что нормально, потому что я запускаю его после ShowDialog). Я пытался вызвать его из общедоступной функции ExecutorWindow(), но тогда получается наоборот: окно открывается только после завершения RunProcessingJob.
Я не знаю, как это заказать .. поведение, которое я хочу, это: — нажать кнопку — открыть окно — запустить задание обработки (без дальнейшего взаимодействия с пользователем) — обновить окно во время выполнения
Должен ли я запускать свое задание по обработке в BackgroundWorker, вызываемом в общедоступном ExecutorWindow () ?
В этом задании обработки уже интенсивно используются BackgroundWorkers, и я не уверен, что это элегантный способ..
РЕДАКТИРОВАТЬ: я обновил свой код на основе ваших комментариев (запуск непосредственно моего окна без создания другого потока. Кроме того, я запускаю свое задание обработки из конструктора window, но теперь в отдельном потоке, чтобы предотвратить проблемы с блокировкой, которые у меня были).
Ответ №1:
Это полностью зависит от того, что Executor.RunProcessingJob
делает; на вопрос нельзя ответить, не посмотрев на этот код.
Однако, почему вы создаете ExecutorWindow
в другом потоке? Если вы хотите, чтобы оно оставалось отзывчивым на пользовательский ввод, у вас нет другого выбора, кроме как выполнить вашу обработку в еще одном потоке (вы упомянули BackgroundWorker
, так что это, вероятно, уже происходит). Но если вы сделаете это, в первую очередь, нет необходимости создавать ExecutorWindow
в своем собственном потоке.
Комментарии:
1. Привет, Джон, задание Runprocessing создает несколько фоновых рабочих, которые выполняют некоторые сетевые операции (задержка выполнения может варьироваться от 60 секунд до 5 минут). Одновременно выполняется X фоновых программ (X определено ранее) и дождитесь завершения работы фоновой программы, прежде чем запускать другую. Как только все они будут запущены, оно вернется. В идеале я хотел бы обновлять панель выполнения в моем ExecutorWindow каждый раз, когда один из этих фоновых рабочих завершает работу или сообщает о прогрессе.
Ответ №2:
Я думаю, вам следует запустить поток обработки в вашем классе ExecutorWindow. Подключите его к какому-либо событию, например, к загрузке. Также я не думаю, что вам нужен отдельный поток для создания и отображения вашего ExecutorWindow. (Если вы не хотите модальный диалог, просто вызовите Show() вместо ShowDialog())
Ответ №3:
Переопределите ExecutorWindow
метод OnInitialize
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
RunExecutor();
}