【问题标题】:Backgroundworker abort后台工作者中止
【发布时间】:2009-03-05 10:28:13
【问题描述】:

我最近尝试使用 backgroundworker 而不是“经典”线程,我意识到至少对我而言,它导致的问题多于解决方案。 我有一个后台工作程序运行同步读取(在这种情况下从 serialPort)并在 1 个代码行中被阻塞大约 30 秒,然后取消挂起不是解决方案。我看到如果应用程序此时关闭(使用十字按钮和 Application.Exit()),该进程将永远保持僵尸状态。

我需要一种方法来强制中止或终止后台工作线程。

【问题讨论】:

    标签: c# winforms backgroundworker


    【解决方案1】:

    我把一个(我认为)放在一起可以完成这项工作。请让我知道我是否离开了。 以下是它的工作原理的简单示例。

    var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true};
    
    backgroundWorker.DoWork += (sender, args) =>
             {                 
                     var thisWorker = sender as BackgroundWorker;
                     var _child = new Thread(() =>
                                                   {
                                                       //..Do Some Code
    
                                                   });
                     _child .Start();
                     while (_child.IsAlive)
                     {
                         if (thisWorker.CancellationPending)
                         {
                             _child.Abort();
                             args.Cancel = true;
                         }
                         Thread.SpinWait(1);
                     }                 
             };
    
     backgroundWorker.RunWorkerAsync(parameter);
     //..Do Something...
    backgroundWorker.CancelAsync();
    

    由于后台工作者是线程池的一部分,我们不想中止它。但是我们可以在内部运行一个线程,我们可以允许中止发生。然后 backgroundWorker 基本上会一直运行,直到子线程完成或者我们向它发出信号以终止该进程。然后后台工作线程可以返回读池。通常,我会将其包装在一个辅助类中,并通过我希望后台线程运行的委托方法作为参数传入并在子线程中运行。

    如果我把我的头撞到墙上,但它似乎工作正常,请告诉我。但这不是线程的问题。当你在不同的时间运行它时,你可以获得不同的结果。

    【讨论】:

    • 这是一个有趣的解决方案,但在我看来,创建一个包装 Thread 对象及其交互的类会更有效,而不是使用 BackgroundWorker 作为中介。据我所知,真的没有理由这样做。
    【解决方案2】:

    进程不应该变成僵尸,因为 BackgroundWorker 线程被标记为“后台”并且应该在 UI 关闭时结束。

    【讨论】:

    • 这是真的,因为 BW 在幕后使用 ThreadPool 类。
    【解决方案3】:

    我不太确定您要完成什么,但也许SerialPort.DataReceived 事件是更好的解决方案?

    如果你已经精通线程的使用,我看不出使用 BackgroundWorker 有什么意义。它是为那些一开始就不懂线程的人设计的。

    此外,我不喜欢中止线程的想法。感觉很危险,多线程应用程序不需要再冒险了。

    【讨论】:

    • 我发现 SerialPort.DataReceived 在 CF 中有点混乱,不知道 impl 在 FF 中是否更好。 CF 使用的线程比您预期的要多,所以要小心。
    • 对于 BackgroundWorker 的评论几乎想为 -1;它旨在强制执行某些标准并自动将事件编组到 UI 线程,这是使用它的正当理由;无论你走哪条路,不理解线程都会导致问题。
    • 除非有更简单的方法可以从普通线程与 UI 线程同步...
    【解决方案4】:

    我不认为 BackgroundWorker 支持杀死线程。取消操作必须在执行该作业的方法中完成。在您的情况下,我认为常规线程将是最佳选择。

    【讨论】:

      【解决方案5】:

      你可以试试这个:

                  backgroundworker.Dispose();
                  backgroundworker = null;
                  GC.Collect(); //this helps cleans up ram
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-29
        • 1970-01-01
        • 1970-01-01
        • 2011-10-30
        • 2011-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多