用于执行任务的通用类,同时保持UI响应
执行操作时,使窗体等待并仍然响应其他任务。
引言
这是一种实现标准WinForms行为的常用方法,即在UI保持响应并允许用户通过UI知道正在发生某些事情的同时,执行可能需要长时间运行的操作。这可以用于标准的WinForms、WPF或MVP风格的应用程序,这正是我使用它的方式。
背景
其他一些我认为不如这个易于使用的选项
使用代码
下载源代码并按F5 - 提供了三个示例
- UI在执行时锁定的标准行为。
- 新的行为,UI没有被锁定,用户可以知道窗体正在忙碌。
- 当新的行为抛出异常时会发生什么。
为了使用这个,需要使用的窗体或视图必须实现接口 IThreadedExecuterView
,可以在窗体本身或基窗体中实现。
public partial class Form1 : Form, IThreadedExecuterView
{
#region IThreadedExecuterView Members
public void SetWait(bool isEnabled)
{
this.Cursor = (isEnabled ? Cursors.Default : Cursors.WaitCursor);
button1.Enabled = button2.Enabled = isEnabled;
}
public void HandleException(Exception ex)
{
MessageBox.Show("This is your standard error " +
"handling call here for " + ex.Message);
}
下面是一个使用示例 - 无需担心UI线程、创建委托或为异常做任何特殊处理,只需在一个地方处理它们即可。
using (ThreadedExecuter<BusinessObject> executer =
new ThreadedExecuter<BusinessObject>(this))
{
executer
.Process(() =>
{
return GetData(); //executes in background worker
})
.WhenFinished(businessObject =>
{
UseData(businessObject); //executes on UI thread
})
.Run();
}
它适用于值类型或引用类型。这里有一个单元测试演示了它的用法
[Test]
public void TestThreadedExecuterNormalBehavior()
{
int result = 0;
bool didComplete = false;
AutoResetEvent waiter = new AutoResetEvent(false);
IThreadedExecuterView view =
MockRepository.GenerateStub<IThreadedExecuterView>();
using (ThreadedExecuter<int> worker = new ThreadedExecuter<int>(view))
{
worker
.Process(()=>
{
Thread.Sleep(1000);
return 42;
})
.WhenFinished(workerResult =>
{
result = workerResult;
didComplete = true;
waiter.Set();
})
.Run();
}
waiter.WaitOne(2000, false);
Assert.AreEqual(42, result);
Assert.IsTrue(didComplete);
}
历史
- 2009年1月24日 - 初始版本。