Я работаю над приложением, которое имеет основную форму со строкой состояния внизу. Строка состояния содержит ProgressBar и метку, которую я хочу использовать, чтобы показать пользователю текущий прогресс в выполнении некоторой работы. Строка состояния также содержит метку, которую я хочу использовать как нажимаемую кнопку «Отмена».
Раньше я создавал асинхронные интерфейсы, но они всегда основывались на одном действии и использовании фонового работника. Но в этой новой программе есть ряд различных действий, которые пользователь может выполнить, для которых я хочу использовать эту же строку состояния, чтобы показать прогресс. Поэтому я пытаюсь найти способ обобщить и стандартизировать интерфейс к этим элементам управления отчетами о прогрессе в строке состояния.
В некоторых случаях асинхронные процессы создаются с использованием BackGroundWorker, но в других случаях мне нужно создать управление вторичными потоками напрямую.
Вот некоторый наполовину законченный скелетный код того, о чем я думал:
public partial class MyForm: System.Windows.Forms.Form
{
...SNIP...
private void WorkProgressChanged(Object sender, EventArgs args)
{
ProgressChangedEventArgs backgroundWorkerArgs = args as ProgressChangedEventArgs;
ProgressReport formReport = args as ProgressReport; //my own custom progress report class
//tries to cast args to a Background worker args
if (backgroundWorkerArgs != null)
{
// update UI based on backgroundWorkerArgs
}
else if (formReport != null)
{
// update UI basd on formReport
}
else
{
//couldn't figure out what kind of progress report was sent
//update UI based on args.ToString();
}
}
private void cancelButtonToolStripLabel_Click(object sender, EventArgs e)
{
//calls cancel method of current processing
if (this._currentWorkCancelAction != null)
{
_currentWorkCancelAction(); //envoke cancel requet
cancelButtonToolStripLabel.Text = "Canceling"; //shows user that cancel request was made
_currentWorkCancelAction = null; //disaccociates cancel button to prevent user from canceling twice
}
}
private void WorkProcessCompleted(Object sender, EventArgs args)
{
//Reset cancel button
cancelButtonToolStripLabel.Text = "Cancel";
cancelButtonToolStripLabel.Visible = false;
//resets the status label and progress bar
statusToolStripLabel.Text = "";
toolStripProgressBar.Value = 0;
}
....SNIP
}
Таким образом, строка состояния обновляется путем подписки `WorkProgressChanged (Object sender, EventArgs args) на некоторое событие
'и в конечном итоге сбрасывается, когда' WorkProcessCompleted (Object sender, EventArgs args) 'вызывается даже после завершения. Моя метка отмены (кнопка) также должна быть связана, а затем диссоциирована с помощью метода делегата, который будет запрашивать отмену любой выполняемой в данный момент работы.
Таким образом, каждый раз, когда работа выполняется, должна происходить куча вещей. Подписки на события добавляются / удаляются, ссылки на делегаты изменяются и т. Д. И т. Д. Итак, я начал задаваться вопросом, можно ли каким-либо образом инкапсулировать все эти действия в один или два метода многократного использования вместо написания дублирующего кода для каждого действия, которое может выполнить место.
Метод InitWorkProcess()
ниже показывает, как я думаю, это может работать. Хотя я почти уверен, что это неправильный способ использования класса EventDescriptor. Я не мог найти какой-либо другой способ ссылаться на событие как параметр метода. Может быть, это невозможно?
public void InitWorkProcess(EventDescriptor workProgressChangedEvent, EventDescriptor workCompletedEvent, System.Action requestCancel)
{
//subscribe to progress changed
workProgressChangedEvent.AddEventHandler(this, this.WorkProgressChanged);
this._workProgressChangedEvent = workProgressChangedEvent;
//subscribe to process completed
workCompletedEvent.AddEventHandler(this, this.WorkProcessCompleted);
this._workCompletedEvent = workCompletedEvent;
//enable cancel button
if (requestCancel != null)
{
cancelButtonToolStripLabel.Visible = true;
this._currentWorkCancelAction = requestCancel;
}
}
... и я бы изменил метод обработки событий WorkProgressComplete, чтобы отписать отношения событий после завершения работы.
private void WorkProcessCompleted(Object sender, EventArgs args)
{
//Reset cancel button
cancelButtonToolStripLabel.Text = "Cancel";
cancelButtonToolStripLabel.Visible = false;
//resets the status label and progress bar
statusToolStripLabel.Text = "";
toolStripProgressBar.Value = 0;
//unsubscribes WorkProcessCompleted() and WorkProgressChanged() methods
this._workCompletedEvent.RemoveEventHandler(this, this._workCompletedEvent);
this._workCompletedEvent = null;
this._workProgressChangedEvent.RemoveEventHandler(this, this._workProgressChangedEvent);
this._workProgressChangedEvent = null;
}
У кого-нибудь есть предложения, как мне это настроить? Должен ли я просто забыть о методе InitWorkProcess()
и вместо этого добавить / удалить все отношения событие / делегат отдельно для каждого действия? Или есть лучший способ полностью?