开发者

How to abort a thread started inside another function?

Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();

I start a thread named 't' inside the 'Form1_Load' function. I have added a button. When click on that button the thread 't' should stop executing and create a new thread with these parameters.

Monitor moni = new Monitor();
Thread t 开发者_如何学运维= new Thread(() => moni.CurrUsage(nics,950));
t.Start();

I know in the form_load event i can use the

t.Abort();


By making t a member of the form, you can reference it later on in the button-click event handler.

Graceful Abort. Although t.Abort() gets the job done, you might be left with half-processed data in the thread t. You can catch the ThreadAbortException in thread t to gracefully end processing.

Beware of overlap. The second problem is that your thread might not have aborted yet while your new thread has started already. You can prevent that by calling t.Join() after calling t.Abort().

Hope this helps.


Make Thread t a private member of your form.

public partial class MainForm : Form
{
    private Thread t;
}


One way is to make Thread t a global variable (place outside of Form_Load). Then it can be accessed and modified from any method in that class.

To instantiate the thread, use t = new Thread(.....

Before aborting the thread, make sure it is not null.


You need to make the Thread object accessable in both places that you need to access it. In this case, making it a private varaible would work.

e.g.

public class MyClass
{
  private Thread MyThread
  {
    get;
    set;
  }


  private void myfunc1()
  {
    MyThread = new Thread(() => moni.CurrUsage(nics,200)); 
    MyThread.Start();
  }

  private void myfunc2()
  {
    MyThread.Abort();

    //  I really need to wait until this thread has stopped...
    MyThread.Join();
  }

}


Adding to the already given answers:

Note that .Join() will block your current (UI) thread, leaving your application unresponsive to the user.

Just as another take: avoid using .Abort() by using a flag in your Monitor class to exit the task you are doing if possible. You can then still wait for .Join(), but you have full control of the state in the background thread.

public class Monitor
{
    private bool _cancel = false;

    public void Cancel()
    {
        _cancel = true;
    }

    public void CurrUsage(Nics nics, int n)
    { 
        _cancel = false;
        // ...
        while (!_cancel)
        {
        // do some stuff
        }
    }
}

in your Form

private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
    _monitor.Cancel()
    _t.Join()       // will return as your background thread has finished cleanly
    _t = new Thread(() => _monitor.CurrUsage(nics,950));   
    t.Start();   
}


As others have pointed out, all you need in order to call Abort is a reference to the thread (just like any other object in .NET).

However

You should seriously consider rethinking this approach. In general, calling Abort is discouraged, as it does not give the target thread sufficient opportunity to reach a stopping point. While it's sometimes appropriate (or the only option), it's almost always a better idea to ask the target thread to stop (usually through a volatile bool rather than forcing it like this.

For example,

public class ThreadClass
{
    private volatile bool stopRequested;
    private Thread thread;

    public void Start()
    {
        stopRequested = false;
        thread = new Thread(ThreadMethod);

        thread.Start();
    }

    public void Stop()
    {
        stopRequested = true;

        if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not 
                                               // completed within 5 seconds
    }

    private void ThreadMethod()
    {

    }
}

Your code then goes into ThreadMethod. Within the method, periodically check the value of stopRequested. If it's true, perform whatever cleanup is necessary (if any) and gracefully return out of the thread. If the content is a loop, the general practice is to place the check at the start of the loop (assuming that the loop is sufficiently tight) and exit early if the value is true. The exact placement is really dependent upon the code, but the general idea is that it should be checked often enough to make the thread exit fairly quickly after it gets set, regardless of when that happens.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜