【问题标题】:Return from a BackgroundWorker from within a method called by it从 BackgroundWorker 从它调用的方法中返回
【发布时间】:2012-10-24 22:59:28
【问题描述】:

我有一个BackgroundWorker,它调用一个调用一个方法的方法......在某处我检查CancellationPending并想退出BackgroundWorker

有没有办法直接从那个深度嵌套的方法中做到这一点,还是必须返回给它的调用者,而后者又会返回给它的调用者......?

【问题讨论】:

    标签: c# winforms backgroundworker


    【解决方案1】:

    您使用BackgroundWorker这一事实并没有什么特别之处 - 请按照与处理深度嵌套方法调用相同的术语来考虑这一点。

    换句话说,不,我想不出(不可怕的)方法可以直接做到这一点。

    我能想到的最简洁的方法是在从每个嵌套方法返回后立即在每个级别检查CancellationPending(如果true,则返回)。

    在顶层抛出特定异常并捕获相同的特定异常类型可以让您快速退出,但这并不是最佳实践(也就是说,不要使用任何非异常的异常,例如正常的流控制)。

    【讨论】:

      【解决方案2】:

      调用方法的BackgroundWorker调用方法...

      有没有办法直接从那个深度嵌套的方法中[取消]

      你可以抛出一个异常。但这与仅对错误使用异常的一般建议相提并论。

      【讨论】:

        【解决方案3】:

        有很多方法,我更喜欢这个实现,虽然它限制了一点参数,但你可以改变它。要点是您将引用作为参数传递给BackgroudWorker

        bkgw = new BackgroundWorker();
        bkgw.DoWork += new DoWorkEventHandler(bkgw_DoWork);
        bkgw.WorkerSupportsCancellation = true;
        
        
        
        void bkgw_DoWork(object sender, DoWorkEventArgs e)
        {
                BackgroundWorker b = (BackgroundWorker)sender;
                if (b.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                if (!Method1(b))
                {
                    e.Cancel = true;
                    return;
                }
                if (b.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
        
        }
        
        bool Method1(BackgroundWorker caller)
        {
            //some code
            if (caller.CancellationPending)
                return false;
            if (!Method2(caller))
                return false;
            //some code
            return true;
        }
        bool Method2(BackgroundWorker caller)
        {
            //some code
            if (caller.CancellationPending)
                return false;
            //some code
            return true;
        }
        

        【讨论】:

          【解决方案4】:

          你可以,但你不应该。

          除了其他答案中提到的抛出异常之外,没有人敢说的邪恶是Thread.Abort()。如果您从在 BackgroundWorker 线程上执行的函数中调用它,则整个线程将退出。 Thread.Abort() 的弊端已被详细讨论elsewhere on this site

          话虽如此,正确的做法是构建你的代码,以便当一个深度嵌套的函数决定线程应该退出时,这个意图被传播到堆栈中的主线程方法,然后可以退出干净利落

          【讨论】:

          • 后台线程本身是要离开的,而不是调用者,所以thread.abort没有任何用处或地方。正如其他人所说,您可以显式抛出异常。实际上,thread.Abort 会很多那么糟糕。您可以确保抛出异常的方式不会导致死锁,实际上会退出线程,不会留下未处理的资源等。这仍然是一个不好的做法,但这是一个相当不错的做法更宜居。
          • 我的意思是深度嵌套的函数可以在当前线程上调用 Thread.Abort() 。我相信这与提问者的问题有关,除非我从根本上误解了某些东西。
          • 调用 thread.abort 只会在该线程中引发异常,因此对自己调用 abort 与仅引发异常并没有什么不同,但在异常消息中引发显式异常会更好会更合适。注意Thread.Abort的大部分问题都是直接从另一个线程调用的结果,所以你不知道异常会从哪里抛出。它可以从阻塞 IO 调用的中间抛出,在 finally 块或 catch 块中,它可能被线程捕获和吞噬,等等。
          猜你喜欢
          • 1970-01-01
          • 2012-03-21
          • 1970-01-01
          • 1970-01-01
          • 2013-12-24
          • 2015-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多