0

I am using thread to multi tasks in winform solution, trying to abort the thread while its working but its not aborting, here is , is there any solution for this situation? need to make the thread abort/quit smoothly without any issues !

also is there any idea of how I can make the thread pause/resume?

Thanks in advance!

Thread CommentingThread;
     CommentingThread = new Thread(async () =>
    {

        AddLog("Commenting process has been started!");

        if (CommentBTN.InvokeRequired)
        {
            CommentBTN.Invoke((MethodInvoker)delegate () {




                CommentBTN.Text = "Stop"; });
        }
        else
        {
            CommentBTN.Text = "Stop";
        }

        if (UrlListview.InvokeRequired)

        {

            if (UrlListview.InvokeRequired)
            {
                UrlListview.Invoke((MethodInvoker)async delegate ()
                {



                    foreach (ListViewItem item in UrlListview.Items)
                    {
                        XtraMessageBox.Show(item.Text);
                        int timetodelay = RandomNumber.Next(int.Parse(CommentsMinDelayNumric.Value.ToString()), int.Parse(CommentsMaxDelayNumric.Value.ToString()));
                        await Task.Run(async () =>
                        {

                            await Task.Delay(timetodelay * 1000);

                        });

                    }
                    CommentBTN.Text = "Start";
                    AddLog("Commenting process has been finished sucessfully!");

                });
            }



        }
        else
        {
            foreach (ListViewItem item in UrlListview.Items)
            {
                XtraMessageBox.Show(item.Text);
                int timetodelay = RandomNumber.Next(int.Parse(CommentsMinDelayNumric.Value.ToString()), int.Parse(CommentsMaxDelayNumric.Value.ToString()));
                await Task.Run(async () =>
                {

                    await Task.Delay(timetodelay * 1000 );

                });

            }

                CommentBTN.Text = "Start";
            AddLog("Commenting process has been finished sucessfully!");



        }






        #endregion
    });
    CommentingThread.Start();

    if (CommentBTN.Text == "Stop")
    {
        CommentBTN.Text = "Start";
        CommentingThread.Abort();

        AddLog("Commenting process has been stopped!");


    }
J. Mark
  • 47
  • 5
  • 2
    I recommend checking out [this article](http://www.albahari.com/threading/) which goes over threading, options for starting/stopping/cancelling, and some different patterns. In general though if you have some list of items to process and what you're wanting to do is CPU bound then you could start up a thread (e.g. Task.Run, PLINQ, or Parallel). If it's I/O bound then consider using async methods (if available). In either case you can use a CancellationToken to cancel the processing. – C. Mitchell Oct 13 '18 at 22:38

1 Answers1

2

First of all, looking at your code, it seems that the Thread may stop immediately if UrlListview.Items does not contain any elements. You might be missing a while loop in this case.

Regarding the issue of stopping the thread: Calling CommentingThread.Abort() will raise a ThreadAbortException which effectively crashes the thread (see the Microsoft Docs for more info for more info. To shut a thread down gracefully you should either declare CancellationTokenSource or a boolean which can be set to true (or false, depending on your implementation), to notify the thread that it needs to be stopped. Here is an example:

var myThread_ctoks = new CancellationTokenSource();
Thread myThread = new Thread( async () =>
{
    while (!myThread_ctoks.IsCancellationRequested) // simulate many long actions
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        Console.WriteLine("Iteration finished!");
    }
});
myThread.Start();  // start the thread

await Task.Delay(TimeSpan.FromMinutes(1));  // lets do some other work
myThread_ctoks.Cancel(); // and now shut down the thread

This thread checks every 2 seconds if a shutdown is required (because the simulated action takes that long). As soon as cancellation is requested (myThread_ctoks.IsCancellationRequested is set to true), the while condition will be false and thus the thread will end. The benefit of doing it this way is that the thread will be shut down in a safe, defined way as it actually shuts down gracefully and doesn't crash.

Regarding how you could pause and resume a thread. You could also use a variable to control that, just by checking if the thread is allowed to do work or not. If it should pause then you would just wait for a second in a while loop.

There is also the possibility to use Thread.Suspend() and Thread.Resume(). There is however the possibility, according to Microsoft that you could lock up other threads under certain circumstances. Additionally, you do not know exactly what code is being executed when you interrupt it. Which may lead to further unexpected behaviour. Thats why I am thinking its best to use a variable to control the thread behaviour.

GHXX
  • 86
  • 1
  • 7
  • 1
    Use the right tools for the right job. If you want to cancel a thread use a CancellationToken. Not only does it actually work correctly (contrary to the Boolean that's missing the visibility qualifiers), it's clearer what it does and you get lots of functionality for free (such as being able to stop the thread even if it's doing say a http request). – Voo Oct 14 '18 at 00:25
  • Dude - I don't know who downvoted you but thanks for at least taking the time to answer. If you can correct your answer and comment here with my userid, I will offset the downvote. – Missy Oct 14 '18 at 00:37
  • @Voo using a cancellation token does not give you more functionality in all cases. In this case particularly there are no actions which even use a cancellation token, which makes it mostly useless and causes extra overhead. Using a boolean would be more efficient ;) – GHXX Oct 14 '18 at 00:53
  • @Ghxx The "extra overhead" comes from actually being correct. If you use a volatile Boolean I doubt there will be any measurable difference in performance. Really, the main reason to use it is because high-level constructs give you a much better chance to write correct concurrent code which is already hard enough without trying to optimize things. – Voo Oct 14 '18 at 01:29
  • @Voo this is a valid reason why to use it, although a single bool is more memory efficient. But both options are perfectly fine and in the end it depends entirely on the situation you use it in. If you got methods that can make use of the cancellation token then using a boolean is useless if you want to cancel the inner actions immediately. If you just run a while loop and do some math then a cancellation token is likely overkill. But as said before, it depends. Additionally, if using a cancellation token, it may be better to run it using a task as that accepts a cancellation token directly. – GHXX Oct 14 '18 at 01:37
  • @GHXX Once again the original code you had with the Boolean was **wrong**. I'd say that "works correctly" is an excellent reason to pick the high-level solution. – Voo Oct 14 '18 at 09:15
  • @Voo I guess we can agree to disagree then. – GHXX Oct 14 '18 at 09:55
  • @GHXX If you don't understand why your first version was wrong you can ask on SO or read up on the .NET memory model yourself. This is not a subjective point, using a Boolean without volatile or any other form synchronization/ordering primitive means there's no guarantee that the flag will be read at the right time. This is one of the most basic errors with concurrent programming and there's [dozens of questions about it](https://stackoverflow.com/questions/1222184/do-i-need-to-lock-or-mark-as-volatile-when-accessing-a-simple-boolean-flag-in-c) – Voo Oct 14 '18 at 11:08
  • Perfect Answer ! – J. Mark Oct 14 '18 at 23:16