后台工作者中止

发布于 2024-07-14 17:58:28 字数 210 浏览 5 评论 0 原文

我最近尝试使用后台工作程序而不是“经典”线程,我意识到至少对我来说,它造成的问题多于解决方案。 我有一个后台工作人员运行同步读取(在本例中是从串行端口)并在 1 行代码中被阻塞大约 30 秒,然后取消挂起不是解决方案。 我发现如果应用程序此时关闭(使用十字按钮和 Application.Exit()),则进程将永远保持僵尸状态。

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

I recently tried to use backgroundworker instead of "classic" threads and I'm realizing that it's causing, at least for me, more problems than solutions.
I have a backgroundworker running a synchronous read (in this case from serialPort) and getting blocked around 30 seconds in 1 code line, then cancellationpending isn't the solution. I'm seeing that if the application gets closed at this point (either with the cross button and Application.Exit()) the process keeps zombie forever.

I need a way to force abort or to kill the backgroundworker thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

苏璃陌 2024-07-21 17:58:28

我把一个组合在一起(我认为)可以完成这项工作。 如果我休息了,请告诉我。
这是其工作原理的一个简单示例。

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 基本上会运行,直到子线程完成或者我们向它发出信号以终止进程。 然后后台工作线程可以返回到读取池中。 通常,我会将其包装在一个帮助程序类中,并传递我希望后台线程运行的委托方法作为参数传入,并在子线程中运行该方法。

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

I put one together that (i think) does the job. Please let me know if im waaaay off.
Here is a simple exaple of how it works.

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();

Since the background worker is part of the thread pool, we dont want to abort it. But we can run a thread internally which we can allow an abort to occur on. The backgroundWorker then basically runs until either the child thread is complete or we signal to it to kill the process. The background worker thread can then go back into the read pool. Typically I will wrap this up in a helper class and pass through the delegate method that I want the background thread to run passed in as the parameter and run that in the child thread.

Please someone let me know if im banging my head against a wall but it seems to work fine.. But thats the problem with threads isnt it.. the varying results you can get when you run it at different times.

抱猫软卧 2024-07-21 17:58:28

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

The process should not become a zombie, since the BackgroundWorker thread is marked as "background" and should end when the UI is closed.

掀纱窥君容 2024-07-21 17:58:28

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

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

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

I'm not very sure on what you're trying to accomplish, but maybe the SerialPort.DataReceived event is a better solution?

If you're already proficient with the usage of threads, I don't see the point in using BackgroundWorker. It's designed for people who don't understand threads in the first place.

Besides, I don't like the idea of aborting a thread. It feels dangerous, and multithreaded applications don't need any more risk taking.

善良天后 2024-07-21 17:58:28

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

I don't think the BackgroundWorker supports killing of the thread. Cancelling an operation must be done in the method that performs the job. In your case I think a regular thread will be the best option.

荒路情人 2024-07-21 17:58:28

你可以试试这个:

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

You can try this:

            backgroundworker.Dispose();
            backgroundworker = null;
            GC.Collect(); //this helps cleans up ram
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文