Winfrom界面异步操作的一个解决方法
2009-07-21 21:44 Animax! 阅读(2605) 评论(4) 收藏 举报
首先定义为界面需要两个部分:
1、界面的逻辑操作部分
2、界面显示部分
基本思路如下:
> 界面逻辑操作部分提供支持方法以及支持方法列表。
> 界面显示部分主动触发逻辑操作,并把操作完成后界面操作内容封装为一个闭包传入逻辑操作部分。
> 界面逻辑操作在每次操作完成后激发界面显示部分闭包的操作内容。
下面就定义一个界面逻辑操作的基类来处理异步的操作:
    public class ViewOperation
    {
        private class ActionEventState
        {
            public ActionEventState()
            {
                IsEndInvoke = false;
            }
            public Guid EventID { get; set; }
            public Control View { get; set; }
            public LogicActionHandler handler { get; set; }
            public object CallBackValue { get; set; }
            public bool IsEndInvoke { get; set; }
        }
        protected delegate object LogicActionHandler(object data);
        public delegate void ActionCallBack(object ActionState);
        protected Dictionary<string, LogicActionHandler> ActionHandlerList = new Dictionary<string, LogicActionHandler>();
        private Dictionary<Guid, ActionCallBack> _actionCallBackList = new Dictionary<Guid, ActionCallBack>();
        /// <summary>
        /// 异步操作执行
        /// </summary>
        public void DoAction(Control view, string ActionKey, object Data, ActionCallBack callBack)
        {
            Guid EventID = Guid.NewGuid();
            _actionCallBackList.Add(EventID, callBack);
            if (ActionHandlerList.ContainsKey(ActionKey))
            {
                LogicActionHandler handler = ActionHandlerList[ActionKey];
                var i = handler.BeginInvoke(Data, ActionCallback, new ActionEventState() { EventID = EventID, View = view, handler = handler });
            }
        }
        private void ActionCallback(IAsyncResult ar)
        {
            ActionEventState state = (ActionEventState)ar.AsyncState;
            if (!state.IsEndInvoke)
            {
                object callBackValue = state.handler.EndInvoke(ar);
                state.CallBackValue = callBackValue;
                state.IsEndInvoke = true;
            }
            if (state.View.InvokeRequired)
            {
                state.View.Invoke(new AsyncCallback(ActionCallback), new object[] { ar });
            }
            else
            {
                // 回调
                if (_actionCallBackList.ContainsKey(state.EventID))
                {
                    try
                    {
                        if (_actionCallBackList[state.EventID] != null)
                            _actionCallBackList[state.EventID](state.CallBackValue);
                    }
                    catch (Exception ex)
                    {
                        // TODO : 错误处理
                    }
                    finally
                    {
                        _actionCallBackList.Remove(state.EventID);
                    }
                }
            }
        }
}
使用Demo:
逻辑操作的类,需要注册它所拥有的方法:
    public class Viewlogic : ViewOperation
    {
        public Viewlogic()
        {
            base.ActionHandlerList.Add("SomeOperation", new LogicActionHandler(SomeOperation));
        }
        private object SomeOperation(object data)
        {
            Thread.Sleep(Convert.ToInt32(data.GetType().GetProperty("waitTime").GetValue(data, null)));
            return data.GetType().GetProperty("Msg").GetValue(data, null).ToString();
        }
    }
界面调用,按照方法的Key调用改方法:
     new Viewlogic().DoAction(this, "SomeOperation",
         new
         {
             waitTime = 2000,
             Msg = "viewMsg"
         },
         new ViewOperation.ActionCallBack(o =>
             {
                 MessageBox.Show(o.ToString());
             }));
这个方法的缺点:
> 界面和逻辑数据传递就依靠一个object,界面需要知道传入的数据和放回的数据。
> 界面需要知道能调用的方法。这个虽然是在一个列表中,可以在逻辑类中列出他拥有的方法,但是在开发时没有环境支持。
> 在回调过程中界面出现错误,VS是会在ViewOperation中报错。
 
                    
                     
                    
                 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号