2011-11-24 3 views
1

내 VS2010 Windows Forms 응용 프로그램이 종료되는 이유에 대해 신비가 있습니다.내 Winforms 앱이 예기치 않게 종료되지만 오류가없는 이유는 무엇입니까?

내 기본 형태로 발생합니다. 이 양식에는 충분히 잘 실행되는 "데이터 다운로드 관리자"클래스의 인스턴스가 있습니다. 양식의 코드에서 양식의 데이터를 업데이트하는 콜백 대리자, DataDownloadManager의 상태를 표시하는 레이블을 연결합니다.

데이터 다운로드 관리자의 상태 변수가 변경 될 때마다 대리인이 호출됩니다. 데이터 다운로드 시간을 설정할 때 (데이터 다운로드 관리자의 상태가 "예약 됨"과 같이) 예상대로 작동합니다. 내 타이머가 작동을 멈추고 델리게이트에 전달 된 메서드를 실행하면, 단계를 거치면서 대부분의 방식대로 작동하는 것으로 보입니다 (아래 참조, UpdateFormData()의 세 가지 폼 레이블 중 처음 두 개를 올바르게 설정합니다).하지만 "lblDataDwnLoadManagerStatus"의 텍스트를 변경하기 위해 행을 가져 오지만 오류는 없지만 즉시 종료됩니다.

한순간에 오류가 발생하지 않았지만 크로스 스레딩 예외를 언급 한 디버그 모드에서 플라이 아웃 메시지를 다시 만들 수 없습니다. 나는 이것이 분명히 희망한다.

도움이 될 것입니다. 아래 코드는 TradingAppDataRunManager가 아래에 포함 된 DataRunManager의 모든 기능을 가져 오는 방식입니다.

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(); 
    } 
+0

중 하나는 출력 창을 확인하거나 모든 예외의보고 가능 - 스튜디오는 기본적으로 많은 예외에 대해 알려하지 않습니다 시각을. 디버그 -> 예외로 이동 한 다음 공용 언어 런타임 예외에 대해 클릭 한 다음 확인을 클릭합니다. 코드를 다시 실행하여 예외가 발생하는지 확인하십시오. –

답변

4

WinForms 컨트롤이 생성 된 다른 스레드에서 절대로 액세스하면 안됩니다.

DataRunManager 클래스가 처리를 위해 별도의 스레드를 사용 중이고 해당 스레드가 StatusChanged 이벤트를 발생시키는 경우 이벤트 처리기가 업데이트중인 WinForms 레이블을 만든 스레드와 다른 스레드에서 처리되고 있습니다. 따라서 ... 당신은 아마 로깅와 AppDomain.UnhandledException 이벤트

AppDomain currentDomain = AppDomain.CurrentDomain; 
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); 

을 처리 할 필요가 또는 여기에서 무엇 이건 ... 다음과 같은 라인을 따라

private void UpdateFormData() 
{ 
    this.Invoke(UpdateFormDataImpl); 
}  

private void UpdateFormDataImpl() 
{ 
    lblDataDwnLoadManagerStatus.Text = Convert.ToString(drm.Status); 
} 
+0

Phil, 고마워 ... 나는 새로운 스레드를 사용하여 대리인에게 새로운 것을 알았습니다. 명시 적으로 그렇게하지 않고도 다른 스레드가 "분리 된"방식으로 몰랐습니다. 이것은 Windows Forms 환경에서만 대리인이이 유형의 관심사입니까? – StatsViaCsh

+0

받은 예외는 스레드 간 문제를 나타내며 다른 스레드에서 WinForm 컨트롤에 액세스 할 수 없다는 것을 알고 있기 때문에 추가 스레드를 사용하고있는 것으로 추측합니다. RunMainDataProcedure 및 ScheduleDataRun을 확인하여 해당 작업에 스레드를 만들고 있는지 확인하십시오. –

+0

그게 내 다음 단계 야. 어딘가에서 발생하지 않거나 내재적 인 경우가 아니면 내 코드가 별도의 스레드를 생성하지 않습니다. 모든 레벨에서 델리게이트 기간을 처음 사용하기 때문에 더 많은 독서를해야합니다. – StatsViaCsh

2

를 이벤트 핸들러를 변경

static void MyHandler(object sender, UnhandledExceptionEventArgs args) { 
     Exception e = (Exception) args.ExceptionObject; 
     Console.WriteLine("MyHandler caught : " + e.Message); 
    } 

이 예외는 상단까지 버블 링되어 응용 프로그램을 종료합니다.

캐치 여기에 전체 마이크로 소프트 페이지 ... http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

+0

Btw 이것은 양식을 열기 전에 Program.Main 메소드에 있어야합니다. – JTew

+0

안녕하세요, 지금 구현하려고합니다 ... 감사합니다. – StatsViaCsh

관련 문제