在程序制作过程中,UserControl需要放置到主窗体MainForm中,由于UserControl需要用到MainForm中的一些数据,所以建立了一个专门的Model类来保存这些数据:

View Code
public class DealReleaseModel:INotifyPropertyChanged
   {
        private long dealId;
        public long DealId
        {
            get { return dealId; }
            set
            {
                if (dealId != value)
                {
                    dealId = value;
                    NotifyPropertyChanged("DealId");
                }
            }
        }

        private int majorVersion;
        public int MajorVersion
        {
            get { return majorVersion; }
            set { majorVersion = value; NotifyPropertyChanged("MajorVersion"); }
        }


        private int privateVersion;
        public int PrivateVersion
        {
            get { return privateVersion; }
            set { privateVersion = value; NotifyPropertyChanged("PrivateVersion"); }
        }

        private int newState;
        public int NewState
        {
            get { return newState; }
            set { newState = value; NotifyPropertyChanged("NewState"); }
        }

        private string newStateStr;
        public string NewStateStr
        {
            get { return newStateStr; }
            set { newStateStr = value; NotifyPropertyChanged("NewStateStr"); }
        }

        private string dealVersionHandle;
        public string DealVersionHandle
        {
            get { return dealVersionHandle; }
            set { dealVersionHandle = value; NotifyPropertyChanged("DealVersionHandle"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
                PropertyChangedEventHandler property_changed = PropertyChanged;
                if (property_changed != null)
                {
                    property_changed(this, new PropertyChangedEventArgs(info));
                }
        }
}

这个类是通过INotifyPropertyChanged进行监视的,一旦有值发生改变,便会马上抛出通知来.

然后在UserControl中,将这个Model中的一些字段通过DataBindings给绑定起来,由于更新过程中,有跨线程操作,所以通过Control.Invoke进行调用:

public void Bind()
{
        txtDaemonDealId.Invoke((Action)(() =>
        {
            txtDaemonDealId.DataBindings.Add("Text", DataCache.dealReleaseModel, "DealId");
        }));
}

通过DataBindings将Model的DealId字段绑定到了TextBox上.

然后我又新建了一个DataCache静态类,以便保存Model中的值.

public static DealReleaseModel dealReleaseModel = new DealReleaseModel();

这一切都完成后,我在MainForm主窗体中开始操纵这个静态类:

public void SubscribeNotification(IntPtr dealInfo)
{
            //some code here
            DataCache.dealReleaseModel.DealId = info.dealId;
            DataCache.dealReleaseModel.MajorVersion = info.majorVersion;
            DataCache.dealReleaseModel.PrivateVersion = info.privateVersion;
            DataCache.dealReleaseModel.NewState = info.newState;
            DataCache.dealReleaseModel.NewStateStr = info.newStateStr;
            DataCache.dealReleaseModel.DealVersionHandle = info.dealVersionHandle;
            //some code here
}

这个SubscribeNotification是通过委托来创建的,主要用于回调,所以运行在了一个异步线程上.这样之后,程序编译通过,运行.第一次运行正常,但是一旦这个Model中有对象被改变的时候就会抛出:

Cross-thread operation not valid: Control 'txtDaemonDealId' accessed from a thread other than the thread it was created on.

我用异步操作txtDaemonDealId了呀,为什么还会出现问题了?

原因呢?

其实, SubscribeNotification本身处于一个线程中,而txtDaemonDealId绑定肯定处于另一个线程(UI线程)中,如果两个处理均在同一个线程中进行,肯定会发生阻塞,导致界面假死。如果从一个直接访问另外一个,肯定是要出现问题的(由于采用了INotifyPropertyChanged接口,所以Model的任何改变都会自动更新到前台UI上),所以在这里,我们要以异步方式来更新Model,让其数据的更新可以和UI进行交互.

修改为:

 this.Invoke((Action)(() =>
      {
                DataCache.dealReleaseModel.DealId = info.dealId;
                 DataCache.dealReleaseModel.MajorVersion = info.majorVersion;
                DataCache.dealReleaseModel.PrivateVersion = info.privateVersion;
                DataCache.dealReleaseModel.NewState = info.newState;
                DataCache.dealReleaseModel.NewStateStr = info.newStateStr;
                DataCache.dealReleaseModel.DealVersionHandle = info.dealVersionHandle;
            }));

一切问题解决.

posted on 2012-11-02 17:38  程序诗人  阅读(1571)  评论(1编辑  收藏  举报