安全停止长时间运行的任务 [英] Safely stop long running task

查看:54
本文介绍了安全停止长时间运行的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是如何停止长时间运行的任务(.net 4)?我已经实现了TPL,并尝试使用CancellationTokenSource,但它似乎不适用于我的情况.我见过的所有示例都假设您正在执行while循环工作,以便您可以检查任务是否已取消,而我只有一个操作需要很长时间.我迫不及待想完成工作,因为我需要假设它可能永远不会完成.这是我尝试过的代码:

My question is how can I stop a long running task (.net 4)? I have implemented TPL and tried using the CancellationTokenSource but it doesn’t seem to work for my scenario. All examples I’ve seen assume you’re doing work in a while-loop so that you can check if the task has been cancelled, whereas I just have a single operation that takes long. I cannot wait for the work to be completed as I need to assume it might never complete. Here is the code I have tried:

        bool? result = null;

        var cs = new CancellationTokenSource();
        var ct = cs.Token;

        var doWorkTask = new Task(() =>
        {
            Console.WriteLine("start dowork task");

            result = Work.LongRunning();
         }, ct);

        doWorkTask.Start();

        Task.WaitAny(new Task[] { doWorkTask }, timetowait);

        if (doWorkTask.IsCompleted)
        {
        Console.WriteLine("dowork task completed");

            doWorkTask.Dispose();
        }
        else
        {
        Console.WriteLine("dowork task has timedout");

            cs.Cancel();

            throw new TimeoutException("Timeout hit.");
        }

代码可以工作,但是如果超时"发生并且正在完成的工作访问非托管代码"(即资源),则永远不会处理任务.那就是说IsCancelledRequested不能在Work.LongRunning()中使用,所以我不能ThrowIfCancellationRequested.

The code works but the task is never disposed if the "timeout" happens and the work that is being done accesses "unmanaged code" i.e. resources. That said the IsCancelledRequested cannot be used in Work.LongRunning() so I cannot ThrowIfCancellationRequested.

除了尝试使用BackgroundWorker之外,我还愿意接受其他想法,但这似乎不合适.

I am open to other ideas as well as I have tried BackgroundWorker but that also doesn’t seem to fit.

新示例:

var service = new System.ServiceProcess.ServiceController(ServiceName, ServerName);

        var serviceTask = Task.Factory.StartNew(() =>
        {
            result = (service.Status == ServiceControllerStatus.Running
                 || service.Status == ServiceControllerStatus.StartPending);
        }, cs.Token);

        serviceTask.Wait(2000, cs.Token);

        if (!serviceTask.IsCompleted)
        {
            cs.Cancel();
        }

推荐答案

下面是示例1所描述的示例(例如,仅杀死Task而不发出信号取消)

Here is an example for option 1 described obove ( i.e. just killing the Task without signalling cancellation)

class Program
    {
        private static void Main(string[] args)
        {
            Test test = new Test();
            test.Run();

            Console.WriteLine("Type c to cancel");
            if (Console.ReadLine().StartsWith("c"))
            {
                Console.WriteLine("cancellation requested");
                test.CancellationTokenSource.Cancel();
            }

            Console.ReadLine();
        }
    }

    public class Test
    {
        private void DoSomething()
        {
            Console.WriteLine("DoSomething runs for 30 seconds ");
            Thread.Sleep(new TimeSpan(0, 0, 0, 30));
            Console.WriteLine("woke up now ");
        }

        public CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

        public void Run()
        {
                var generateReportsTask = Task.Factory.StartNew(() =>
                {
                    CancellationTokenSource.Token.ThrowIfCancellationRequested();
                    Task doSomething = new Task(DoSomething, CancellationTokenSource.Token);
                    doSomething.Start();

                    doSomething.Wait(CancellationTokenSource.Token);
                }, CancellationTokenSource.Token);

                generateReportsTask.ContinueWith(
                    (t) =>
                    {
                        if (t.Exception != null)
                            Console.WriteLine("Exceptions reported :\n " + t.Exception);

                        if (t.Status == TaskStatus.RanToCompletion)
                            Console.WriteLine("Completed report generation task");
                        if (t.Status == TaskStatus.Faulted)
                            Console.WriteLine("Completed reported generation with unhandeled exceptions");
                        if(t.Status == TaskStatus.Canceled)
                            Console.WriteLine("The Task Has been cancelled");
                    });

        }
    }

这篇关于安全停止长时间运行的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆