Reputation: 1000
This problem caused the program to run a few minutes. Before I used System.Timers.Timer
and not found problem ,until I changed to System.Threading.Timer
.
I would like to know that ...
What is a root cause of this problem ?
How to solve this problem ?
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 Class
Property 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 Constructor
public TimerManager(frmMainServer main)
{
_timer = new System.Threading.Timer(new
TimerCallback(tmrThreadingTimer_TimerCallback),
null, System.Threading.Timeout.Infinite, 1000);
_main = main;
}
OnTimeChanged
private void OnTimeChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
Timer callback
private void tmrThreadingTimer_TimerCallback(object state)
{
TimeSinceStartTime += TimeSpan.FromSeconds(1);
}
Computer Class
Important Property
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);
}
}
}
If time changed calculate fee, notify Usedtime and 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");
}
Main Form
Set CompList gridview datasource with dbBindingSource and set dbBindingSource datasource with Computers binding list.
public BindingList<Computer> computers = new BindingList<Computer>();
.
.
.
compList.DataSource = dbBindingSource;
dbBindingSource.DataSource = computers;
Upvotes: 0
Views: 1674
Reputation: 2638
The root cause is that you're changing a data source in a non-UI thread bound to a UI control. The easiest solution is to use a System.Windows.Forms.Timer which will always execute on the UI thread, however, it's not very high resolution or accurate. Your next option is to make sure your PropertyChanged are raised on the UI thread using a SynchronizationContext or by using Invoke/BeginInvoke.
Upvotes: 2