How to access and stop a Thread? ASP.NET C #

3

Developing in ASP.NET MVC5 and within Action of POST I start a Thread :

[HttpPost]
[AutorizacaoFilterAttribute]
public ActionResult ProcessarEmails(ProcessEmailModel model)
{
    ViewBag.Processing = false;

    if (ModelState.IsValid)
    {
        if (EmailAnalisys.State == AnalyseStatus.Stopped || EmailAnalisys.State == AnalyseStatus.Finished)
        {
           Thread thread = new Thread(() => EmailAnalisys.FilterErrorEmails(model.Label, model.Email));
           thread.Start();
            ViewBag.Processing = true ;
         }
     }
     return View(model);

}

How do I abort the Thread since I no longer have access to it since I have already returned the View ?

Edit: The need to return a View () is because it imagines that the email box has 1000 messages, and I am processing 1 to 1, I need to show the user which message is being processed, type "1/1000 "> "2/1000", that's why I need to return to View ().

    
asked by anonymous 12.03.2018 / 18:42

3 answers

6

Thinking about an answer to the question, and taking the hook from the discussion with @perozzo, who already posted a solution using Thread.Abort , I was thinking of other ways to abort thread , things like semaphores by example, and I came across the interesting MVP article Joydip Kanjilal: My two cents on the Thread.Abort and Thread.Interrupt methods

In this article, it addresses some aspects of using Thread.Abort() and Thread.Interrupt() , and recalls that in thread we can handle this (detect that it was aborted) using ThreadAbortException .

In the article he also remembers that neither method is thread-safe (if you do not know the concept, you can read more here: Thread safety ), that is, we have to treat the competition with shared resources.

The part that really caught the eye was that he, in his opinion, does not recommend abort thread using Thread.Abort() for example (in free translation):

  

My honest answer is that you should never use any of these   methods to terminate a thread . It is advisable not to use the Thread.Abort   or Thread.Interrupt to terminate a thread - you should instead,   take advantage of synchronization objects (such as WaitHandles or    Semaphores ) and quit "gracefully" the threads   is using.

Another idea he mentions is to use a variable boolean volatile shared with the thread , which is checked to continue thread execution in> and can be altered by another thread , thus making it gracefully shut down as it mentions.

An example code from the C # Programming Guide :

// variável de controle
internal volatile bool _shouldStop;

// método para "parar a thread", que vai setar a variável
public void RequestStop()
{
   _shouldStop = true;
}

// método da thread
public void DoWork()
{
   while (!_shouldStop)
   {
       Console.WriteLine("worker thread: working...");
   }
   Console.WriteLine("worker thread: terminating gracefully.");
}

Another way to do something similar is by using an object CancellationTokenSource . This piece of code (based on In MSDN ) shows an example:

var cts = new CancellationTokenSource();

void ExecutarThread() 
{
    // inicia o token
    cts = new CancellationTokenSource();
    // Passa o token para a thread
    Task.Run(() => DoWork(cts.Token), cts.Token);
}

void CancelarThread()
{
    cts.Cancel();
    cts.Dispose();
}

void DoWork(CancellationToken token)
{
  while (alguma_condicao_de_loop)
  {
     // verifica se foi cancelado
     if (token.IsCancellationRequested) {
        Console.WriteLine("I was canceled while running.");
        // sai e trata
        break;  
        // ou dispara uma exception tratada pelo token
        token.ThrowIfCancellationRequested();
     }
  }
}

Codes are examples adapted to demonstrate the functionality, probably need some adjustment to work in each scenario, but are other ways to try to abort a thread .

    
13.03.2018 / 13:31
1

What you're trying to do is a bad design . Note that your request is returned without thread termination, but what if the thread throws an exception and does not finalize its operation correctly? As you will know about this if you do not have a logging system, and worse than that, you have probably already presented a successful message to the user.

Aborting a thread can cause many problems, if you abort the thread in the middle of its execution you may have data inconsistency. And since you've already returned the main thread, you have no way of knowing if this thread has finished its work.

For all answers about Thread.Abort() , it's worth noting that does not guarantee the completion of a thread . When you call Thread.Abort() , you cause Thread to receive a ThreadAbortException , but it can call Thread.ResetAbort() and cancel the request.

The most correct thing is to wait for the thread to return:

Thread thread = new Thread(() => EmailAnalisys.FilterErrorEmails(model.Label, model.Email));
thread.Start();
//Se tiver algo para fazer a mais, pode ser feito aqui.
thread.Join();

So your main thread will wait for the thread to be terminated, and in case something goes wrong with the thread I can handle it effectively (I do not explain in the code how to do this).

Of course, doing so my code has lost the benefits of using the thread. That's why I said bad design. To know a good way to work with thread in your case would have to know what FilterErrorEmails implements.

    
13.03.2018 / 14:09
-1

You can use Thread.Abort . According to your code, thread.Abort(); .

But according to a post by Eric Lippert, it is not certain that this will actually stop the Thread , without speaking which is risky to use.

Follows:

  

Let me add that there are no guarantees that calling Thread.Abort will actually abort the thread in question. It is possible (but not at all easy) to make it difficult for a thread to be aborted. If for example you are aborting a thread because you believe it is running a hostile code and then the hostile code may be resisting its own destruction. Home   If you have a long operation involving code that you are not responsible for that needs to be stopped correctly, the correct way to do this is to place the code in your own process, not in your own thread. (And preferably in a highly secure-restricted process). Then you can properly kill the process.   In short, Thread.Abort is the best indicative of bad design, possibly unreliable, and extremely dangerous. Should be avoided at any cost; the only time you should consider abort a thread is in case of some "emergency shutdown" code where you are trying to shutdown a appdomain as cleanly as possible.

    
12.03.2018 / 19:16