Reputation: 2640
I'm mystified as to why my VS2010 Windows Forms app is getting shut down.
It happens in my main form. This form has an instance of a "data download manager" class that runs well enough. In the form's code I tie into a delegate for a callback to update data on the form, labels that display the status of the DataDownloadManager.
The delegate is invoked whenever Status variables in the Data Download Manager change. This works as expected, such as when I set a data download time (the status of the data download manager is "Scheduled"). When my timer goes off and runs my method passed to the delegate it seems to work most of the way as I step through it (see below, it correctly sets the first two of the three form's labels in UpdateFormData()), but when it gets to the line to change the text of "lblDataDwnLoadManagerStatus", there is no error, but it promptly exits.
At one point I didn't have an error but a flyout message in debug mode that mentioned a cross- threading exception, that I can't recreate. I hope this is clear.
Any help would be great. Code is below, and by the way TradingAppDataRunManager gets all functionality from DataRunManager, included below.
public partial class frmTradingAppMain : Form
{
private TradingAppDataRunManager drm;
public frmTradingAppMain()
{
InitializeComponent();
}
private void frmTradingAppMain_Load(object sender, EventArgs e){}
private void frmTradingAppMain_Shown(object sender, EventArgs e)
{
drm = new TradingAppDataRunManager();
drm.StatusChanged += new DataRunManager.StatusChangeHandler(this.UpdateFormData);
drm.InitializeOrScheduleDataRun();
}
private void UpdateFormData()
{
MessageBox.Show("This is a test");
lblNextScheduledDataDownloadDate.Text = drm.DateTimeOfNextScheduledDataRun.ToShortDateString();
lblNextScheduledDataDownloadTime.Text = drm.DateTimeOfNextScheduledDataRun.ToShortTimeString();
lblDataDwnLoadManagerStatus.Text = Convert.ToString(drm.Status);
}
private void btnSetChangeOrCancelScheduledDataRunTime_Click(object sender, EventArgs e)
{
drm.InitializeOrScheduleDataRun();
}
private void btnExit_Click(object sender, EventArgs e)
{
Close();
}
}
public abstract class DataRunManager
//The base class for the upper- level, overall management for an app's data downloading and processing.
{
private List<DataCollection> dataCollectionList = new List<DataCollection>();
private List<PerformanceTrackerPoint> performanceTrackerPoint;
private List<Error> errorCollection;
protected DataRunTimer timer;
protected SqlConnection sqlConnection;
public enum DRMStatus { Running, Scheduled, Inactive }
public DRMStatus Status { get; set; }
public DateTime DateTimeOfNextAvailableDataRun { get; set; } //This is the time that is checked from the database.
public DateTime DateTimeOfNextScheduledDataRun { get; set; } //This is the time that gets set for the run.
public delegate void StatusChangeHandler();
public event StatusChangeHandler StatusChanged;
protected abstract String SQLSelectStringForDateOfLastDataRun();
protected abstract void SetDBConnection();
protected abstract List<DataCollection> GetDataCollectionsFromSubclass();
public void InitializeOrScheduleDataRun()
{
DateTimeOfNextAvailableDataRun = DateTimeOfNextDataRun();
if (DataRunIsOverdue())
{
if (UserWouldLikeToPerformDataRun())
{
Status = DRMStatus.Running;
RunMainDataProcedure(null);
}
else
{
ScheduleDataRun();
Status = DRMStatus.Scheduled;
}
}
StatusChanged();
}
Upvotes: 1
Views: 2698
Reputation: 22906
You should never access a WinForms control from a different thread to which it was created on.
If your DataRunManager class is using a separate thread for some processing and then that thread is firing the StatusChanged event then the event handler is being processed on a different thread than the one that created the WinForms labels you are updating. Therefore change your event handler along the following lines...
private void UpdateFormData()
{
this.Invoke(UpdateFormDataImpl);
}
private void UpdateFormDataImpl()
{
lblDataDwnLoadManagerStatus.Text = Convert.ToString(drm.Status);
}
Upvotes: 4
Reputation: 3179
You probably need to handle the AppDomain.UnhandledException Event
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
With the Logging or whatever in here ...
static void MyHandler(object sender, UnhandledExceptionEventArgs args) {
Exception e = (Exception) args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
}
This should catch any exceptions that bubble all the way to the top and terminate your application.
Catch the full Microsoft page here ... http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Upvotes: 2