65.9K
CodeProject 正在变化。 阅读更多。
Home

用于执行任务的通用类,同时保持UI响应

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (19投票s)

2009年1月24日

CPOL

1分钟阅读

viewsIcon

101025

downloadIcon

700

执行操作时,使窗体等待并仍然响应其他任务。

1.jpg

引言

这是一种实现标准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日 - 初始版本。
© . All rights reserved.