如何“杀死” 完全是后台工作者吗?

发布于 2024-07-19 07:51:54 字数 600 浏览 5 评论 0原文

我正在编写一个 Windows 应用程序,它重复运行一系列数字 IO 操作。

当用户单击“开始”按钮时,这一系列操作就会开始,并由后台工作人员在 backgroundWorker1_DoWork() 中完成。

但是,有时我会收到“此后台工作人员当前正忙......”错误消息。

我正在考虑在代码中实现以下内容,在开始另一个操作序列之前使用 while 循环来“杀死”后台工作人员:

if (backgroundWorker1.IsBusy == true)
{

    backgroundWorker1.CancelAsync();
    while (backgroundWorker1.IsBusy == true)
    {
        backgroundWorker1.CancelAsync();
    }

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();

我认为我主要关心的是,backgroundWorker1 最终会被“杀死”吗? 如果可以的话,会需要很长时间才能完成吗?

这个编码会让我陷入无限循环吗?

I am writing a windows application that runs a sequence of digital IO actions repeatedly.

This sequence of actions starts when the user click a "START" button, and it is done by a background worker in backgroundWorker1_DoWork().

However, there are occasions when I get the "This backgroundworker is currently busy......." error message.

I am thinking of implementing the following in the code, by using a while loop to "kill" the background worker before starting another sequence of action:

if (backgroundWorker1.IsBusy == true)
{

    backgroundWorker1.CancelAsync();
    while (backgroundWorker1.IsBusy == true)
    {
        backgroundWorker1.CancelAsync();
    }

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();

I think my main concern is, will the backgroundWorker1 be "killed" eventually? If it will, will it take a long time to complete it?

Will this coding get me into an infinite loop?

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

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

发布评论

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

评论(6

谎言 2024-07-26 07:51:54

您可以使用类似的内容(有关中止托管线程和 ThreadAbortException 的更多信息,请参阅“使用 Rotor 探究 ThreadAbortException 的深度(网络存档),作者:Chris Sells):

public class AbortableBackgroundWorker : BackgroundWorker
{

    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }

 
    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

用法:

backgroundWorker1 = new AbortableBackgroundWorker();
//...
backgroundWorker1.RunWorkerAsync();

if (backgroundWorker1.IsBusy == true)
{
    backgroundWorker1.Abort();
    backgroundWorker1.Dispose();
}

You can use something like this (for more information about aborting managed threads and about ThreadAbortException see "Plumbing the Depths of the ThreadAbortException Using Rotor (Web archive)" by Chris Sells):

public class AbortableBackgroundWorker : BackgroundWorker
{

    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }

 
    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

Usage:

backgroundWorker1 = new AbortableBackgroundWorker();
//...
backgroundWorker1.RunWorkerAsync();

if (backgroundWorker1.IsBusy == true)
{
    backgroundWorker1.Abort();
    backgroundWorker1.Dispose();
}
我的鱼塘能养鲲 2024-07-26 07:51:54

我认为线程应该尽可能对其自己资源负责,包括它们自己的生命周期。

从线程外部杀死线程通常是一个坏主意。范围。 设计为将消息传递给线程以关闭自身的应用程序往往会出现与多线程行为相关的问题少得多。

线程应该及时监视所述消息,该消息可以像另一个线程设置的布尔值一样简单,并由该监视线程读取,并尽快干净地关闭自己。

查找消息:(

  • 这意味着它是否应该在主循环中
  • 如果有)。 在任何长时间运行的循环中定期执行。

使用消息关闭它的线程应该等待(但当然不要停止 GUI)。

请注意,具有特定功能的线程环境还有其他可能性,例如线程可以随意将自己标记为可取消的情况,以允许外部终止更安全。

但通常仍然更容易构建您的应用程序,让线程主控者自己决定命运。

I'm of the opinion that threads should be responsible for their own resources as much as practicable, including their own lifetime.

It's usually a bad idea to kill threads from outside their scope. Applications that are engineered to pass a message to the thread to shut itself down tend to have far less problems related to multi-threaded behavior.

A thread should monitor for said message, which can be as simple as a boolean set by another thread and read by that monitoring thread, in a timely fashion and shut itself down cleanly as soon as it can.

That means if it should look for the message:

  • in it's main loop, if any.
  • periodically in any long-running loops.

The thread shutting it down with the message should wait (but don't halt the GUI, of course).

Note that there are other possibilities for threaded environments with specific capabilities such as the case where threads can mark themselves cancellable at will, to allow external killing to be safer.

But it's still usually easier to just architect your application to leave a thread master of its own destiny.

热情消退 2024-07-26 07:51:54

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

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-26 07:51:54

我遇到了同样的问题,我不确定这是否有帮助,但我猜你的后台工作人员有一个循环,否则它会退出。
您需要做的就是将循环放入其中。

放入你的后台工作者:

while (backgroundworker1.CancellationPending == false)
{
    //Put your code in here
}

要杀死这个后台工作者,你可以放入你的按钮:

BackgroundWorker1.CancelAsync()

我希望这会有所帮助。

I was having the same problem, I'm not sure if this will help but I'm guessing your background worker has a loop within or it would exit.
What you need to do is put your loop within.

Put inside your background worker:

while (backgroundworker1.CancellationPending == false)
{
    //Put your code in here
}

To kill this backgroundworker, you can put in your button:

BackgroundWorker1.CancelAsync()

I hope this helps.

哑剧 2024-07-26 07:51:54

我只是使用“返回”转到线程末尾:

private void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
   // some variables 

   while(true)
   {
      // do something ...
      if(need_cancel) return;
      else doSomeThingElse();
   }

   // may be more code here (ignored if 'return' is executed) ...
   // .........
   // .........
}

i just use a 'return' to go to end of thread:

private void myWorker_DoWork(object sender, DoWorkEventArgs e)
{
   // some variables 

   while(true)
   {
      // do something ...
      if(need_cancel) return;
      else doSomeThingElse();
   }

   // may be more code here (ignored if 'return' is executed) ...
   // .........
   // .........
}
溺ぐ爱和你が 2024-07-26 07:51:54
public class abortableBackgroundworker: BackgroundWorker
{
    public bool Kill = false;

    protected override void OnDoWork(DoWorkEventArgs e)
    {


        var _child = new Thread(() =>
        {
            while (!Kill)
            {

            }
            e.Cancel = true;//..Do Some Code

        });
        _child.Start();
        base.OnDoWork(e);

    }



}

你将kill设置为true来终止线程并且没有中止问题:)

public class abortableBackgroundworker: BackgroundWorker
{
    public bool Kill = false;

    protected override void OnDoWork(DoWorkEventArgs e)
    {


        var _child = new Thread(() =>
        {
            while (!Kill)
            {

            }
            e.Cancel = true;//..Do Some Code

        });
        _child.Start();
        base.OnDoWork(e);

    }



}

you set kill to true to kill the thread and no abort problem :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文