简体   繁体   中英

WPF Stop BackgroundWorker from main thread

i have a BackgroundWorker that execute work in the background. the work is run some .exe application in command prompt and wait for output for display. sometimes the .exe app is stack or takes a lot of time. i want to stop the worker after one minute in case it is still running. the issue is that i have a progress bar that runs in the main thread for 1 minute. i want to stop the worker when the progress bar is full (after 1 minute) from the main thread (UI) . here is my code:

    private void btnTest_Click(object sender, RoutedEventArgs e)
    {

        wTest = new BackgroundWorker();
        wTest .DoWork += new DoWorkEventHandler(wTest _DoWork);
        wTest .RunWorkerCompleted += wTest _RunWorkerCompleted;
        wTest .WorkerReportsProgress = true;
        wTest .WorkerSupportsCancellation = true;
        wTest .RunWorkerAsync();

        while (pbTest.Value < 91)
        {               
            if (!wTest.CancellationPending)
            {
                pbTest.Value = (pbTest.Value + 100/60);
                Thread.Sleep(1000);
            }
            Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background,
                                       new ThreadStart(delegate { }));
        }
    }

    void wTest_DoWork(object sender, DoWorkEventArgs e)
    {
        //call .exe application and wait for output
    }

how can i do it?

If you are using .net 4.5, you can use the Task class and the associated CancellationTokeSource and CancellationToken classes. Note that tasks support reporting progress through the IProgress interface. Stephen Cleary has a good example on this.

If the work you were doing does not provide an asynchronous interface you can use Task.Run to execute it and pass a CancellationToken to monitor for cancellation. As you are doing the work you need to monitor the token for cancellation. One way to do this is to call ThrowIfCancellationRequested which will throw a OperationCancelledException if Cancel has been called on the CancellationTokenSource . CancellationTokenSource also supports cancellation after a certain time, which will be handy for your scenario.

private CancellationTokenSource cts;

private void btnTest_Click(object sender, RoutedEventArgs e)
{
    if(cts == null)
    {
        cts = new CancellationTokenSource(new TimeSpan(0, 0, 60)); // cancel after 60 seconds
    }

    await Task.Run( () => Work(), cts.Token);

    cts = null;
}

void Work(CancellationToken token)
{
   // do work
  token.ThrowIfCancellationRequested();
  // do work
}

You will need to do two things to enable work cancellation of your BackgroundWorker . First, you will need to check for the BackgroundWorker.CancellationPending property in your DoWork handler method:

private void wTest_DoWork(object sender, DoWorkEventArgs e)
{
    //call .exe application and wait for output
    if (worker.CancellationPending)
    {   
        e.Cancel = true;
    }
}

Then, when you want to cancel the work, you should call this on your BackgroundWorker :

backgroundWorker.CancelAsync();

However, as you are not using the BackgroundWorker as it was meant to be used, I don't think that this will work for you. If you are waiting for the third party application to start, then you won't be able to set the e.Cancel property to true .

To be honest, I can't quite understand why you would use a BackgroundWorker just to start a process anyway. The Process.Start method takes no time to complete as it doesn't wait for any response. In my opinion, you'd be better off monitoring the Process.Exited event and calling the Process.Kill method instead.

What you need to do is have your DoWork delegate check for e.Cancel (in DoWorkEventArgs ) property bring set to true . If DoWork is blocking, like waiting for StandardOutput , then that simply wont be possible.

Another approach would be to pass Process.WaitForExit an int stating how long it should wait for output:

process.WaitForExit(60000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM