C # - How to force close a background worker that launches its own threads

I have a wpf application, let's call it A-app

. A-app

works asyncronic B-method

with background worker. This B-method

is in another project and creates multiple threads for the B-method

init part .

The user may be asked to start B-method

and may be asked to cancel the launch and restart. The problem is that if it is canceled during initialization, the background worker that starts B-method

is canceled, but the threads are not. Restarting creates more threads that cannot run at the same time as threads from the previous run and causes some errors.

The Threads method basically waits.

How can I stop B-method

as well as cancel the threads it has created?

Can any other AppDomain help? (and how to close the entire application domain?) If so, how to do it? Is there a better way?

More details:

  • The B method runs tests on some devices (there may be many). the initiator of the method connects to devices - i / o - so most of the time is spent waiting (this is the reason we decided to do a parallel connection in parallel) .tring to connect to the same device from 2 different threads can cause problems.
+3


source to share


2 answers


I would assume that you are not creating Threads at all, but using TaskScheduler and working with a parallel tasks library:

http://msdn.microsoft.com/en-us/library/dd997402%28v=vs.110%29.aspx

The TaskScheduler itself is a wrapper around the ThreadPool that handles threads. It even makes stuf like WorkStealing, Task Inling, etc.

Best case scenario, you start here: http://msdn.microsoft.com/en-us/library/dd997402%28v=vs.110%29.aspx

Another approach is to start Tasks with a CancalletionToken, which allows you to cancel Tasks. See here: http://msdn.microsoft.com/en-us/library/dd537607%28v=vs.110%29.aspx



Edit: Okey, no TPL, block threads. This leaves basically just Thread.Abort. It's messy, but there is no perfect world, so think of a form as app A and ClassB as app B:

public partial class MainWindow : Window
{
    Thread _threadA;
    Thread _threadB;
    Thread _threadC;

    ClassB b1 = new ClassB();
    ClassB b2 = new ClassB();
    ClassB b3 = new ClassB();

    public MainWindow()
    {
        InitializeComponent();

        _threadA = new Thread(() => b1.DoSomeWork("A"));
        _threadB = new Thread(() => b2.DoSomeWork("B"));
        _threadC = new Thread(() => b3.DoSomeWork("C"));
    }

    private void btnStartWork_Click(object sender, RoutedEventArgs e)
    {
        _threadA.Start();
        _threadB.Start();
        _threadC.Start();
    }

    private void btnStopThreadA_Click(object sender, RoutedEventArgs e)
    {
        AbortThreadA();
    }

    private void btnStopThreadB_Click(object sender, RoutedEventArgs e)
    {
        AbortThreadB();
    }

    private void btnStopThreadC_Click(object sender, RoutedEventArgs e)
    {
        AbortThreadC();
    }

    private void AbortThreadA()
    {
        _threadA.Abort();
    }

    private void AbortThreadB()
    {
        _threadB.Abort();
    }

    private void AbortThreadC()
    {
        _threadC.Abort();
    }

    private void btnStopAll_Click(object sender, RoutedEventArgs e)
    {
        AbortThreadA();
        AbortThreadB();
        AbortThreadC();
    }
}



class ClassB
{
    public void DoSomeWork(string threadIdentifier)
    {
        try
        { 
            string preWorkString = "Work work Okeydokey. Thread: " + threadIdentifier;
            string postWorkString = "Job Done. Thread: " + threadIdentifier;

            while (true)
            {
                System.Diagnostics.Debug.WriteLine(preWorkString);
                Thread.Sleep(5000);
                System.Diagnostics.Debug.WriteLine(postWorkString);
            }
        }
        catch (ThreadAbortException)
        {
            System.Diagnostics.Debug.WriteLine("Thread aborted. Thread: " + threadIdentifier);
            Thread.ResetAbort();
        }
    }
}

      

ResetAbort is required, otherwise the error is aborted.

Is this a possible solution?

0


source


You have a B-method (i.e. can you change it?)

My guess is that the B-method cannot be fully invalidated and you are just canceling the background worker that calls it in module A?



The B-method must be changed to either cancel or re-login. By a repeater, I mean that it will allow multiple calls to itself and will reuse any existing init sequence that is already running.

0


source







All Articles