2012-01-24 100 views
0

此問題導致程序運行幾分鐘。在我使用System.Timers.Timer之前沒有發現問題,直到我改爲System.Threading.TimerDatagridview與System.Threading.Timer

我想知道...

什麼是這個問題的根本原因?

如何解決這個問題?

A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll 
    System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>InternetCafe.vshost.exe</AppDomain><Exception><ExceptionType>System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>BindingSource cannot be its own data source. Do not set the DataSource and DataMember properties to values that refer back to BindingSource.</Message><StackTrace> at System.Windows.Forms.BindingSource.get_Count() 
     at System.Windows.Forms.CurrencyManager.get_Count() 
     at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e) 
     at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e) 
     at System.Windows.Forms.BindingSource.InnerList_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.ComponentModel.BindingList`1.OnListChanged(ListChangedEventArgs e) 
     at System.ComponentModel.BindingList`1.Child_PropertyChanged(Object sender, PropertyChangedEventArgs e) 
     at InternetCafe.Computer.NotifyPropertyChanged(String info) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\Computer.cs:line 163 
     at InternetCafe.Computer.UsedTimeValueChanged(Object sender, PropertyChangedEventArgs e) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\Computer.cs:line 149 
     at InternetCafe.TimerManager.OnTimeChanged(PropertyChangedEventArgs e) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 62 
     at InternetCafe.TimerManager.set_TimeSinceStartTime(TimeSpan value) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 30 
     at InternetCafe.TimerManager.tmrThreadingTimer_TimerCallback(Object state) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 50 
     at System.Threading._TimerCallback.TimerCallback_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading._TimerCallback.PerformTimerCallback(Object state)</StackTrace><ExceptionString>System.InvalidOperationException: BindingSource cannot be its own data source. Do not set the DataSource and DataMember properties to values that refer back to BindingSource. 
     at System.Windows.Forms.BindingSource.get_Count() 
     at System.Windows.Forms.CurrencyManager.get_Count() 
     at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e) 
     at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e) 
     at System.Windows.Forms.BindingSource.InnerList_ListChanged(Object sender, ListChangedEventArgs e) 
     at System.ComponentModel.BindingList`1.OnListChanged(ListChangedEventArgs e) 
     at System.ComponentModel.BindingList`1.Child_PropertyChanged(Object sender, PropertyChangedEventArgs e) 
     at InternetCafe.Computer.NotifyPropertyChanged(String info) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\Computer.cs:line 163 
     at InternetCafe.Computer.UsedTimeValueChanged(Object sender, PropertyChangedEventArgs e) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\Computer.cs:line 149 
     at InternetCafe.TimerManager.OnTimeChanged(PropertyChangedEventArgs e) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 62 
     at InternetCafe.TimerManager.set_TimeSinceStartTime(TimeSpan value) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 30 
     at InternetCafe.TimerManager.tmrThreadingTimer_TimerCallback(Object state) in C:\Users\at0m\Documents\Visual Studio 2010\Projects\InternetCafe\InternetCafe\TimerManager.cs:line 50 
     at System.Threading._TimerCallback.TimerCallback_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading._TimerCallback.PerformTimerCallback(Object state)</ExceptionString></Exception></TraceRecord> 

一個TimerManager類

屬性TimeSinceStartTime

public TimeSpan TimeSinceStartTime 
    { 
     get { return new TimeSpan(timeSinceStartTime.Hours, timeSinceStartTime.Minutes, timeSinceStartTime.Seconds); } 
     set 
     { 
      if (timeSinceStartTime != value) 
      { 
       timeSinceStartTime = value; 
       OnTimeChanged(new PropertyChangedEventArgs("TimeSinceStartTime")); 
      } 
     } 
    } 

一個TimerManager構造

public TimerManager(frmMainServer main) 
    { 
     _timer = new System.Threading.Timer(new 
        TimerCallback(tmrThreadingTimer_TimerCallback), 
        null, System.Threading.Timeout.Infinite, 1000); 
     _main = main; 
    } 

OnTim eChanged

private void OnTimeChanged(PropertyChangedEventArgs e) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, e); 
     } 
    } 

計時器回調

private void tmrThreadingTimer_TimerCallback(object state) 
    { 
     TimeSinceStartTime += TimeSpan.FromSeconds(1); 
    } 

計算機類

重要屬性

public decimal TotalMoney 
    { 
     get 
     { 
      return this.totalMoney; 
     } 

     set 
     { 
      if (value != this.totalMoney) 
      { 
       this.totalMoney = value; 
       NotifyPropertyChanged("TotalMoney"); 
      } 
     } 
    } 

    public TimerManager UsedTime 
    { 
     get 
     { 
      return this.usedTimeValue; 

     } 

     set 
     { 
      if (value != this.usedTimeValue) 
      { 
       this.usedTimeValue = value; 
       NotifyPropertyChanged("UsedTimeValue"); 
       usedTimeValue.PropertyChanged += new PropertyChangedEventHandler(UsedTimeValueChanged);  
      } 
     } 
    } 

如果時間改變演算支付費用,通知Usedtime和TotalMoney。

private void UsedTimeValueChanged(object sender, PropertyChangedEventArgs e) 
    { 
     NotifyPropertyChanged("UsedTime"); 
     this.totalMoney = (decimal)(this.UsedTime.TimeSinceStartTime.Hours * this.session.Member.MemberTariff + this.UsedTime.TimeSinceStartTime.Minutes * (this.session.Member.MemberTariff/60)); 
     NotifyPropertyChanged("TotalMoney"); 
    } 

主要形式

集CompList gridview的數據源與dbBindingSource並設置dbBindingSource數據源與計算機綁定列表。

public BindingList<Computer> computers = new BindingList<Computer>(); 
. 
. 
. 
compList.DataSource = dbBindingSource; 
dbBindingSource.DataSource = computers; 
+0

如果它與其他計時器一起工作,你爲什麼改變它? –

+0

因爲當我使用System.Timers.Timer並像這樣設置「tmrTimersTimer.SynchronizingObject = this;」但它基於UI線程。如果UI線程凍結,時間將顯示不正確。所以我會改變爲異步計時器。 –

+0

如果我回答不正確,對不起,我是新的。 :) –

回答

2

根本原因是您要更改綁定到UI控件的非UI線程中的數據源。最簡單的解決方案是使用一個總是在UI線程上執行的System.Windows.Forms.Timer,但是,它不是很高的分辨率或準確性。您的下一個選項是確保在UI線程上使用SynchronizationContext或使用Invoke/BeginInvoke引發PropertyChanged。