1

私は、Windows Mobile 6 で実行される C# アプリケーションに取り組んでいるので、.NET Compact Framework です。バックグラウンド スレッドを使用してネットワーク通信を処理し、UI を解放します。

これらのスレッドはオブジェクト内にあります (別のプロジェクトの一部として記述されています)。メイン アプリはオブジェクトをインスタンス化し、接続を開始するように指示します。すべてのスレッド制御は「接続」オブジェクトによって行われます。

アプリがメニューから終了すると、connection.Stop() メソッドを呼び出します。このメソッドは、接続オブジェクトに切断を指示し、そのリソースを解放して、スレッドをシャットダウンします。これは問題ありませんが、アプリがタスク マネージャーから強制終了された場合、または [実行中のプログラム] ドロップダウンから [X] を押した場合、アプリのメイン GUI は閉じますが、これらのオブジェクトによって開始されたスレッドは閉じません。

デバイスでサードパーティのタスク マネージャーを使用すると、「実行中のアプリケーション」の下にアプリの兆候がないことがわかりますが、「実行中のプロセス」の下にはアプリケーションと同じバイナリが表示されています。アプリケーションを再起動しようとすると、画面にフリックしてから再びオフになります。

アプリが閉じられているイベントをキャッチするにはどうすればよいですか。フォームを閉じることをキャッチすることは、私が探していることではありません。とにかく Closing イベントは発生しないようです。

スレッドに isBackgroundWorker を設定しましたが、これは効果がありませんでした。

アプリが閉じられているのをキャッチできない場合、代わりに、アプリの UI がまだ存在するかどうかをスレッドに確認させ、そうでない場合はシャットダウンさせるにはどうすればよいでしょうか。

**これを入力している間、私は..メインアプリが強制終了され、そのオブジェクトが解放された場合、オブジェクトはメインアプリによってインスタンス化されます..それはこれらのスレッドを途方に暮れたままにしていますか? 「接続」オブジェクトの onDispose でそれらをクリアする必要がありますか?

編集- 要求に応じてコードを追加します。これらは、関連性があると思われる場所から引き出されたスニペットです。アプリは巨大です。これはメインアプリ内です

    public Connection = new Connection(id, server, port, onStatusChange);

    this.Connection.Start();

    onStatusChange is a delegate on the main app

そして接続オブジェクトで.. Connection.Start() は次のようになります。

    public void Start()
    {
        //Since we can't check the thread state then we have to kill the existing thread
        Stop();
        //Should not be able to start a new thread if one is already running
        lock (this.pushLock)
        {
            ConnectionThreadStart = new ThreadStart(ConnectionThreadMethod);
            ConnectionThread = new Thread(ConnectionThreadStart);
            ConnectionThread.Name = "Connection";
            ConnectionThread.IsBackground = true;
            //Start the new thread
            this.start = true;
            ConnectionThread.Start();
        }
    }

    /// <summary>
    /// Method ran by the connection thread
    /// </summary>
    private void ConnectionThreadMethod()
    {
        //Take ownership of ConnectionThread until we exit
        lock (this.pushLock)
        {
            //Keep trying to connect until flag tells us not to
            while (this.start)
            {
              //establish and maintain connection
             }
         }
     }

    public void Stop()
    {
        //Indicate to thread that it should not continue running.
        this.start = false;
        //Attempt to close the socket on which the connection listens, this should cause it to fail with an exception
        try
        {
            Socket.Client.Close();
        }
        catch(Exception e)
        {
        }
        try
        {
            Socket.Close();
        }
        catch(Exception e)
        {
        }
        //If for some reason the thread is still going ask it to abort which, again, should cause it to throw an exception and exit
        try
        {
            ConnectionThread.Abort();
        }
        catch(Exception e)
        {
        }
        //Finally join the thread if it is still going and wait for it to exit. It will give up waiting after 10 seconds
        try
        {
            if (!ConnectionThread.Join(10000))
            {
                //The thread failed to stop, we can do no more, the thing is borken
            }
        }
        catch (Exception e)
        {
        }
    }

したがって、アプリが正常に終了すると、単純に Connection.Stop() を呼び出すだけで終了します。

さらに編集します。-これを追加しました..まだ期待どおりに機能しません。

        private bool disposed = false;

    //Implement IDisposable.
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                Stop();
            }
            disposed = true;
        }
    }

    ~Connection()
    {
        // Simply call Dispose(false).
        Dispose (false);
    }
}
4

1 に答える 1

1

アプリがタスク マネージャーを介して強制的に終了された場合、マネージド アプリはクリーンアップ コードを実行する余裕がありません。それは単純に終了し、それが何をしていたとしてもそのトラックで停止します。まだ実行されていることがわかる場合は、低レベルのドライバーが譲歩を拒否している可能性があります。これらのスレッドがどのような作業を行っているかを確認しなければ、確実に知ることはできません。

WM の「実行中のプロセス」ユーティリティを使用してアプリを終了すると、メッセージがフォーム ウィンドウに投稿されると思われるためWM_QUIT、適切に処理して終了する前にクリーンアップする機会が得られます。

予期しない終了リクエストなどの不測の事態に対処するためにすべきことは、.try/finally ブロックを .xml の周りに配置することApplication.Run()です。finally ブロック内のコードは、アプリが正常にシャットダウンするたびに実行されるため、このようなタイプのクリーンアップ ルーチンを記述するのに理想的な場所です。

これがどのように見えるかを説明する擬似コードを次に示します。

            try
        {
            //application startup code here//


            System.Windows.Forms.Application.Run(new YourMainForm());
        }

        catch (Exception x)
        {
            log.Fatal("FATAL application exception occurred.", x);
           //TODO: decide how to handle fatal exception. Feedback to user?

        }

        finally
        {
            try
            {
                //shut down application activities 
                //shutdown your connection object here                  
            }
            catch (Exception ex)
            {
                log.Error("A fatal error occurred while attempting to shutdown the application", ex);

            }
        }
于 2012-12-14T21:51:51.167 に答える