首页 文章

当应用程序被Windows Mobile 6.x杀死时,整理后台线程

提问于
浏览
1

我正在开发一个在Windows Mobile 6上运行的C#应用程序,因此.NET Compact Framework . 它使用后台线程来处理网络通信并保持UI免费 .

这些线程在对象内(作为另一个项目的一部分编写) . 主app实例化对象,并告诉他们开始连接 . 所有线程控制都由'connection'对象完成 .

当应用程序通过菜单退出时,它会调用connection.Stop()方法,该方法告诉连接对象断开连接,释放其资源并关闭线程 . 这一切都很好,但是如果应用程序被从任务管理器中杀死,或者从“正在运行的程序”下拉列表中点击“X”,则应用程序的主GUI将关闭,但这些对象启动的线程不会 .

在设备上使用第三方任务管理器,我可以看到在“正在运行的应用程序”下没有应用程序的迹象,但它在“运行进程”下面列出了与应用程序相同的二进制文件 . 我尝试重新启动应用程序,然后轻弹到屏幕然后再关闭 .

如何捕捉应用程序被关闭的事件, grab 表单关闭并不是我想要做的事情 - Closing事件似乎无论如何都不会发生 .

我在线程上设置了isBackgroundWorker,但这没有效果 .

如果我无法 grab 应用程序被关闭,我将如何让线程检查应用程序的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);
    }
}

1 回答

  • 1

    如果应用程序通过任务管理器强行终止,那么您管理的应用程序无法获得运行清理代码的奢侈 . 它只是终止了,无论它在做什么都停在它的轨道上 . 如果你可以看到它仍然在运行,那可能是由于较低级别的驱动程序拒绝屈服 . 如果没有看到这些线程正在做什么工作,就不可能确切知道 .

    如果您通过WM "running processes"实用程序终止应用程序,我相信 WM_QUIT 消息会发布到您的表单窗口,因此您有机会正确处理它并在退出前进行清理 .

    你应该做些什么来处理意外退出请求之类的可能性是在 Application.Run() 周围放置一个try / finally块 . 每次你的应用程序正常关闭时,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);
    
                }
            }
    

相关问题