0

I have queue maintained by a single thread. The thread will do some operations on each item of the queue in turn. I want the single thread could skip certain queue item and go on for the next item when I click a button (or some other operation).

Actually I have already had a solution which uses two threads, one used to maintain the queue, the other used to do operations on each queue item. But this causes some trouble when I pause or skip the whole process in real situation. The communication between the two threads seems not working well.

Let's say that the queue has items 1, 2, 3, 4, 5. Assuming that the thread is working on item 1 now. When I click the button, the thread should stop current operation and skip all scheduled operations on item 1 and then work on item 2. Operations on each item is almost the same. Like making dishes, when I am cooking the first dish, I received an command to ignore it, I must throw the first dish away and start cooking the second dish.

I wonder whether it is possible to use a single thread in my scenario?

The code used now is like the following snippet.

ManualResetEvent _rstEvent = new ManualResetEvent(false);
TestItem _currentTest;
public void FuncMaintainTestQueue()
{
  while(TestQueue.Count > 0)
  {
    _currentTest = TestQueue.Deque();
    Thread thread = new Thread(FuncDoTest);
    thread.Start();
    _rstEvent.WaitOne();
  }
}

private void FuncDoTest()
{
  //Do test operations on _currentTest
  ...
  //Finished current test item
  _rstEvent.Set();
}

//Outside caller

Thread _thread1 = new Thread(FuncMaintainTestQueue);
thread1.Start();
Dream Land
  • 31
  • 5
  • *"I want the single thread could skip certain queue item and go on for the next item when I click a button."* -- Could you give an example? Let's say that the queue contains the items 1, 2, 3, 4, 5. What should happen when the button is clicked? – Theodor Zoulias Feb 21 '22 at 04:02
  • @Theodor Zoulias Thank you so much for your comment! Assuming the thread is working on item 1 now. When I click the button, the thread should stop current operation and skip all scheduled operations on item 1 and then work on item 2 with almost the same operations with item 1. – Dream Land Feb 21 '22 at 04:36
  • How are you stopping the current operation? Is it [cancelable](https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads)? – Theodor Zoulias Feb 21 '22 at 04:42
  • @Theodor Zoulias If I was using two-thread solution, I would abort the thread used to do operations on current item and then create a new thread to work on the next item. If using a single thread, maybe I can abort the thread, remove the current item, run the thread again. But it looks bad. – Dream Land Feb 21 '22 at 04:49
  • 1
    Aborting threads is not only [bad](https://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort), it's [not even supported](https://stackoverflow.com/questions/53465551/net-core-equivalent-to-thread-abort) on the newer .NET platforms. So I guess that you are targeting the old .NET Framework. Could you switch to cooperative cancelation instead of aborting threads? What kind of work are you doing with each item? CPU-bound? I/O bound? – Theodor Zoulias Feb 21 '22 at 05:06
  • @Theodor Zoulias Yes it is bad and deprecated by the .NET platforms. The project I am doing is a test app. User can set many test parameters with different values in one test item. These test items are put into a test queue. There are several buttons like stop, pause, skip the current test, cancel the test queue. These old code is written by former employees. I suggested the project group not to use suspend, abort etc. But you know, it works not so bad, so the team does not willing to switch to other choices. – Dream Land Feb 21 '22 at 05:48
  • @Theodor Zoulias I have fixed so many bugs of this pattern for a long time. Could you please give me some suggestions of using what kind of cooperative cancelation? That would be very helpful for me to re-build the pattern. – Dream Land Feb 21 '22 at 05:50
  • The article [Cancellation in Managed Threads](https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads) covers the topic of cooperative cancellation quite thoroughly IMHO. It's unlikely that I could write a general tutorial that would be more useful than this. There are also plenty of questions here (like [this](https://stackoverflow.com/questions/15067865/how-to-use-the-cancellationtoken-property)) about cancelation tokens. I suggest to start on your own, and if you get stuck then come back with concrete code, and with a concrete question about that code. – Theodor Zoulias Feb 21 '22 at 11:50
  • Of course if the work you are doing (the tests) is not cancelable, all this information about cancelation tokens is useless to you. The generally recommended approach when dealing with non-cancelable work is to start it on a separate process, and then cancel it by killing the process. – Theodor Zoulias Feb 21 '22 at 12:06
  • It would be really great if you could show us your code. – Enigmativity Feb 21 '22 at 22:39
  • @Theodor Zoulias Thank you! It helps a lot. – Dream Land Feb 22 '22 at 01:30
  • @Enigmativity I drew an abstraction of the code in my problem's description. – Dream Land Feb 22 '22 at 01:51
  • @DreamLand - It seems like you just need an `if` in `FuncDoTest` that checks if it should exit and calls `_rstEvent.Set()` before it does. – Enigmativity Feb 22 '22 at 06:25
  • @Enigmativity I abort the thread ```FuncDoTest``` when I click the button *Cancel*. The ```FuncDoTest``` has a deep hierarchy, containing thousands of lines of code. This may sound terrible but using suspend or abort seems to be an easier way than writing ```_rstEvent.WaitOne()``` everywhere. – Dream Land Feb 22 '22 at 06:52
  • @DreamLand - `.Abort` can corrupt the run-time making all of your other threads not reliable. That's why it has been removed. You need to post your thousands of lines so that we can comment on how you might fix it. `.Abort` is not an option. – Enigmativity Feb 22 '22 at 09:29

0 Answers0