1

私は子ウィンドウを持つWPFアプリケーションを持っています.その中で、ボタンのクリックで(バックグラウンドワーカーで)データベース接続チェックを行っています。プロセスが完了するまでに時間がかかり、その間にユーザーが [閉じる] ボタンをクリックして子ウィンドウを閉じると、ウィンドウは閉じますが、バックグラウンド ワーカーは引き続き実行され、しばらくするとメッセージが表示されます。

サンプルコードは次のとおりです。

BackgroundWorker worker;
private void Button_Click(object sender, RoutedEventArgs e)
            {
                worker = new BackgroundWorker();
                worker.WorkerSupportsCancellation = true;
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);

                bsyInd.IsBusy = true;
                worker.RunWorkerAsync();
            }
     void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    // checking database connectivity
                    string connstring=myconnstring;
                    SqlConnection con=new SqlConnection(connstring);
                    con.Open();
                    if(con.State==ConnectionState.Open)
                       e.Result=true;
                }
                catch (Exception)
                {
                 e.Result=false;
                }

            }

            void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                bool canConnect=(bool)e.Result;
                if(canConnect)
                    MessageBox.Show("Connected");
                else
                    MessageBox.Show("Failed");

                bsyInd.IsBusy = false;
            }

    //close child window
    private void ChildWindow_CloseButton_Click(object sender, RoutedEventArgs e)
    {
        //cancel the running process
        worker.CancelAsync();
    }

私がオンラインで見つけたすべてのソリューションは、Do_Work 内のループ内でバックグラウンド ワーカーの CancellationPending プロパティを継続的に監視/ポーリングする例を示しています。ここで私が行おうとしているプロセスはループを必要としないので、子ウィンドウの閉じるボタンのクリック イベントで CancellationPending ステータスを監視し、バックグラウンド プロセスをキャンセルするにはどうすればよいですか?

前もって感謝します。

4

2 に答える 2

1

へのブロッキング呼び出しを中止する方法がSqlConnection.Openあれば、SqlConnectionオブジェクトをクラスのメンバ変数として宣言し、閉じるボタン ハンドラで中止呼び出しを実行するだけです。

private SqlConnection con;

private void ChildWindow_CloseButton_Click(object sender, RoutedEventArgs e) 
{ 
    if (con != null)
    {
        con.Dispose(); // or whatever would abort Open()
        con = null;
    }
}  

ワーカー スレッドOpenでは、おそらく Aborted 例外のようなものをスローし、それをキャッチしてから設定することができますe.Cancel = true;

于 2012-08-02T09:44:33.217 に答える
0

Dennis さん、AutoResetEvent を使用したアプローチを使用できます。AutoResetEvent クラスを参照してください。

SQL 接続が発生しているスレッドに、リソースを解放できることを知らせます。

あなたはまだ別のスレッドを使用しているので、何もブロックされるべきではありませんが、スレッド間で通信し、そのうちの 1 つに特別に通知してリソースを解放することができるようになりました。これが意図した形式でない場合は、お詫び申し上げます。

そのリンクには、AutoResetEvent の使用方法の例があります。

于 2012-09-24T20:32:04.440 に答える