2012-04-26 24 views
0

バックグラウンドワーカーを含む単一のフォームを含むWinFormsアプリケーションがあります。このフォームには、RunWorkerAsync()を使用してバックグラウンドワーカーを開始するボタンと、アプリケーションを終了する別のボタンが含まれています。背景労働者が作業を完了した後、私はこのような例外を除いて終了]ボタンをクリックした後、約1/3の時間、アプリケーションがクラッシュします:ここでは未処理のSystem.NullReferenceExceptionで終了すると.NET WinFormsアプリがクラッシュする

System.NullReferenceException was unhandled 
    Message=Object reference not set to an instance of an object. 
    Source=System.Drawing 
    StackTrace: 
     at System.Drawing.Graphics.Dispose(Boolean disposing) 
     at System.Drawing.Graphics.Finalize() 

ボタンのイベントハンドラであること私たちがここを見ているコードパスがちょうど閉じる()の呼び出しである私が先に言ったように、バックグラウンドワーカーがまだ実行されている間、私はアプリケーションを終了していないよ

private void buttonExit_Click(object sender, EventArgs e) 
    { 
     if (!buttonStartWorker.Enabled) 
     { 
      DialogResult dr = MessageBox.Show("Background worker is still running! Exit anyway?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); 

      if (dr == DialogResult.OK) 
      { 
       backgroundWorker.CancelAsync(); 
       Close(); 
      } 
     } 
     else 
     { 
      Close(); 
     } 
    } 

:アプリケーションを終了します。また、私のUSB関連のハンドルでメソッドをcloseおよびdisposeするFormClosingイベントハンドラもあります。そのコードは以下の通りである:いつかwriteHandle.Dispose()とアプリケーションが実際に終了した時間の間に、この例外が発生している

private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
    { 
     try 
     { 
      // close and dispose all open handles to the USB device 
      if (hidHandle != null) 
      { 
       if (!(hidHandle.IsInvalid)) 
       { 
        hidHandle.Close(); 
        hidHandle.Dispose(); 
       } 
      } 

      if (readHandle != null) 
      { 
       if (!(readHandle.IsInvalid)) 
       { 
        readHandle.Close(); 
        readHandle.Dispose(); 
       } 
      } 

      if (writeHandle != null) 
      { 
       if (!(writeHandle.IsInvalid)) 
       { 
        writeHandle.Close(); 
        writeHandle.Dispose(); // unhandled exception seems to occur after this 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex.ToString()); 
     } 
    } 

。私を最も混乱させるのは、私のコードがSystem.Drawingを明示的に使用していないので、これを追跡するのに問題があります。何が価値がある、私の背景労働者は、以下のんのために

  1. それはいくつかのデータを読み取りおよび書き込みに/ USBデバイスから
  2. それは
  3. それをいくつかのデータをダウンロードするWebクライアントを作成しますいくつかのSOAP呼び出しを行います

アプリケーション(System.Draを明示的に使用していないときに、System.Drawingで処理されていないNullReferenceExceptionが発生する可能性があることについて、翼)は出る?

+0

完全なスタックトレースを投稿してください。 – wal

答えて

0

プログラムが明示的にSystem.Drawingを使用していない場合でも、その名前空間はほとんどすべてのWinFormsオブジェクトコードの上にあります。それはあなたのフォームのどこかで、1つのGUIオブジェクトに別のオブジェクトのGraphicsハンドルへの参照が与えられていることが分かります。そのハンドルを所有するコントロールが既に破棄されているか、Graphicsオブジェクト自体にDisposeメソッドが明示的に呼び出されているため、2回目の実行時にDispose()コードが失敗します。私は、.NET開発者がダブルディスポーザルが問題ではないことを確認するために小切手を入れることを期待していただろうが、見落としたように見える。

あなたのウィンドウのフォームと、System.Drawing.Graphicsのどのインスタンスが捨てているかを正確に知らなければ、私はそれ以上の助けにはなりません。それは私がさらに調査するところであろう。 (通常は明示的に処理された場合は、GC.SuppressFinalize()の呼び出しを行う必要があります)、処理が完了した後にファイナライズされている理由を調べます。

「反映された」コードベースの参照の1つが役に立ちます。 System.Drawing.Graphics.Dispose(bool disposing)を探し、2行連続で実行すると失敗するコード行を探します。それはあなたにヒントを与えるかもしれません。

1

KeithSの回答は原則的に正しいですが、コードに目に見える問題があるようです。 CancelAsync()の呼び出しの直後にthis.Close();に電話しています。私は、バックグラウンドワーカーがビジネスを終了するのを待つか、キャンセルされたイベントがあればそれを購読しようとします。

あなたのバックグラウンドワーカーが終了していない可能性があります。また、バックグラウンドワーカーは、フォームのイベントの階層構造と関連するコンポーネントであることにも注意してください。

this.BeginInvoke(new Action(() => (Thread.Sleep(1000); this.Close();)));

は、新しいタスクを作成してみてください。

誤った構文については申し訳ありませんが、私は開発用マシンではありません。

+0

Raheelの提案に感謝します。あなたは確かにCancelAsync()の直後にClose()を呼び出すコードパスに関して有効なポイントを作成します。残念ながら、それはこれまで実行してきたコードパスではありません。私は、バックグラウンドワーカーがまだ実行している間にアプリケーションを終了していません。私のbackgroundWorker_RunWorkerCompleted()メソッド(ここには示していません)では、buttonExit_Click()内のelse節を実行させるbuttonStartWorker.Enabled = trueを設定します。 buttonExit_Click()の最初の行にブレークポイントを置くことでこれを確認しました。 – user685869

関連する問題