【发布时间】:2010-02-25 01:50:59
【问题描述】:
我正在开发一个应用程序,它的主窗体底部有一个状态栏。状态栏包含一个进度条和一个标签,我想用它来向用户显示正在完成的某些工作的当前进度。状态栏还包含一个标签,我想像可点击的取消按钮一样使用它。
我之前已经创建过这样的异步接口,但它们始终基于单个操作,并使用后台工作程序。但是在这个新程序中,用户可能会调用许多不同的操作,我想使用同一个状态栏来显示所有这些操作的进度。所以我试图找出一种方法来概括和标准化状态栏中这些进度报告控件的接口。
在某些情况下,异步进程是使用 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() 方法,而是为每个操作分别添加/删除所有事件/委托关系?还是完全有更好的方法?
【问题讨论】:
标签: c# .net winforms multithreading asynchronous