[转]通用异步线程调用模式--通知线程

目的:对于以交互式的用户界面而言,假如要调用长时间运行的操作,那么可以使用以下模式让你的调用更方便。

问题:某个用户界面必须多次启动某个操作,开发人员希望将其从该接口的操作中分开。这里面可能有很多的理由,但最普遍的情形是多个操作需要被立即执行,或某个操作潜在地占用过多的时间,超过了用户所期望的等待响应时间。某写操作的完成总是要占用时间,在等待某个操作护照或者多个操作在后台执行时,用户界面应该允许用户继续做其他事情。对于web上的操作,现在流行的AJAX热得一塌糊涂,通过异步调用来获取服务器端信息并更新客户端。对于winform来说,当然也可以进行异步调用了。本文试图提供一个稍微通用一点的解决方法。

适用性:
在下列情况下可以使用:
采用胖客户端,WinForm实现。
操作被预期是长期的或者占用时间比较长的
多个操作必须立即被处理执行的

主要包括:
    public delegate void CompleteEvent<T>(T t);   //采用泛型委托,操作的结果被传递给调用方。
    public delegate void ExceptionEvent(Exception ExceptionThrown); //异常将被传递给调用方
    public NotifyingThreadManager<T> //通知线程管理

NotifyingThreadManager<T> 中
 public void ExecuteAsync(System.Windows.Forms.Control ControlToNotify, CompleteEvent<T> NotificationDelegate, ExceptionEvent ExceptionDelegate) 的目标就是存储需要用来通知的信息和启动封装线程的执行。我们需要知道将要同步的控件以及用来处理结果的两个委托。

线程的主要工作在 protected void DoExecution()中完成,可以进行相应的修改以适应实际操作。

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Threading;
 5namespace com.tttick.NotifyingThreadManager
 6{
 7    public delegate void CompleteEvent<T>(T t);
 8    public delegate void ExceptionEvent(Exception ExceptionThrown);
 9    public class NotifyingThreadManager<T>
10    {
11        System.Windows.Forms.Control mControlToNotify;
12        CompleteEvent<T> mFactoringComplete;
13        ExceptionEvent mFactoringErrored;
14        Thread mExecution;
15        T t;
16        public NotifyingThreadManager(T t)
17        {
18            this.t = t;
19        }

20        public void ExecuteAsync(System.Windows.Forms.Control ControlToNotify, CompleteEvent<T> NotificationDelegate, ExceptionEvent ExceptionDelegate)
21        {
22            mControlToNotify = ControlToNotify;
23            mFactoringComplete = NotificationDelegate;
24            mFactoringErrored = ExceptionDelegate;
25            ThreadStart startThread = new ThreadStart(DoExecution);
26            mExecution = new Thread(startThread);
27            mExecution.Start();
28        }

29        protected void DoExecution()
30        {
31            object[] paramArray = new object[1];
32            try
33            {
34                //此处进行一个长时间的操作,请灵活使用
35                Thread.Sleep(10000);
36                paramArray[0]=t;
37                mControlToNotify.BeginInvoke(mFactoringComplete,paramArray);
38            }

39            catch (Exception ex)
40            {
41                paramArray[0= ex;
42                mControlToNotify.BeginInvoke(mFactoringErrored, paramArray);
43            }

44        }

45
46    }

47}


调用操作如下
 1 private void button1_Click(object sender, EventArgs e)
 2        {
 3            NotifyingThreadManager<string> f = new NotifyingThreadManager<string>("gadfg");
 4            f.ExecuteAsync(this.button1, new CompleteEvent<string>(FactoringComplete), new ExceptionEvent(FactoringErrored));
 5        }

 6void FactoringComplete(string Result)
 7        {
 8            this.button1.Text+= Result;
 9        }

10        void FactoringErrored( Exception ExceptionThrown)
11        {
12            this.button1.Text = ExceptionThrown.Message;
13        }

通过异步调用线程,更改按钮的文字显示。
对于构造函数的参数,还有线程的执行,只需要进行相应的修改即可满足要实际要求。

PS:本文部分内容参考<.NET模式>一书
posted @ 2008-07-08 09:02  吴东雷  阅读(478)  评论(1编辑  收藏  举报