基于接口和队列的线程操作UI方式

    在实际开发应用中,非UI线程操作UI是普遍存在的,在.net下一般是通过Control.Invoke的方法来进行操作,但到处都是Control.Invoke代码维护可是一件麻烦的事情。以下通过接口和队列来规范非UI线程操UI的实现。

   既然要规范处理那接口是个不错的选择,以下定义一个简单的执行接口

public interface IInvokeItem
    {
        void Execute();
    }

  以下是扩展一个简单的操作类封装

class ControlInvoke<CONTROL,DATA> : IInvokeItem
    {
        public ControlInvoke(CONTROL control, DATA data, Action<CONTROL, DATA> action)
        {
            mControl = control;
            mData = data;
            mAction = action;
        }
        private CONTROL mControl;
        private DATA mData;
        private Action<CONTROL, DATA> mAction;
        public void Execute()
        {
            mAction(mControl, mData);
        }
    }

  规则定好了,那接下来要做的事情就是写一个简单的队列处理。

public class Dispatch
    {
        static Dispatch()
        {
            Instance = new Dispatch();
        }
        public void Add<CONTROL, DATA>(CONTROL control, DATA data, Action<CONTROL, DATA> action)
        {
            ControlInvoke<CONTROL, DATA> item = new ControlInvoke<CONTROL, DATA>(control, data, action);
            Add(item);
        }
        private Queue<IInvokeItem> mQueues = new Queue<IInvokeItem>();
        public static Dispatch Instance
        {
            get;
            set;
        }
        public void Add(IInvokeItem item)
        {
            lock (this)
            {
                mQueues.Enqueue(item);
            }
        }
        public void Execite()
        {
            lock (this)
            {
                while (mQueues.Count > 0)
                {
                    mQueues.Dequeue().Execute();
                }
            }
        }
    }

  一个简单的调用规则就完成,接下来就是如果在winform下面用了;首先可以在界面定义一个timer,可以指定时间内执行Dispatch的工作。

private void timer1_Tick(object sender, EventArgs e)
        {
            ThreadInvoke.Dispatch.Instance.Execite(); 
        }

  当需要在线程中操作UI只需要向ThreadInvoke.Dispatch添加item即可,对于它的执行是完全不用关心的。以下是起一个线程不停地向一个文本框添加一个GUID值

private void cmdTest_Click(object sender, EventArgs e)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(OnTest);
        }
        private void OnTest(object state)
        {
            while (true)
            {
                ThreadInvoke.Dispatch.Instance.Add<RichTextBox, Guid>(
                    richTextBox1, Guid.NewGuid(), (c, d) => {
                        richTextBox1.AppendText(d.ToString("N"));
                        richTextBox1.AppendText("\r\n");
                    });
                System.Threading.Thread.Sleep(10);
            }
        }

 这样一个不使用Control.Invoke来实现非UI线程操作UI的方法就完成了.至于灵活性来说那就看你如何发挥IInvokeItem了:)

posted @ 2012-08-06 12:33  beetlex  阅读(2428)  评论(7编辑  收藏  举报