任务,线程,工厂,取消 [英] Task, Thread, Factory, Cancel

查看:51
本文介绍了任务,线程,工厂,取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

推荐答案

你真的发布了太多的代码来阅读,所以我只会解决第一个代码块。 

You really posted too much code to read through so I'll just address the first code block. 

要取消任务,任务必须查看是否已取消。如果它永远不会看起来那么它就不会知道。在第一个示例中,您有一条注释,表示您需要在任务完成后使用ContinueWith。那是不对的。在任务完成后,ContinueWith用于
触发额外的工作。如果任务被取消,则继续可能不会运行(取决于您提供的选项)。

To cancel a task the task must look to see if it is cancelled. If it never looks then it won't know. In your first example you have a comment that says that you need to use ContinueWith after the task completes. That is incorrect. ContinueWith is used to trigger additional work after the task completes. If the task is cancelled then the continuation may not run (depends on the options you provide).

您应该很少使用新的任务和启动。请改用Task.Run。这有很多原因,你可以谷歌。理想情况下,你应该完全使用async / await和forego调用Task.Run。这实际上是问题的关键,
您的取消。您正在调用接受2个参数的任务ctor - 操作和状态。因此令牌作为参数(动作代码中的obj)传递给操作,而不是作为取消令牌。当
你进入ContinueWith调用时,任务仍然在后台运行。

You should rarely be using new Task and Start. Use Task.Run instead. There are many reasons for this that you can google for. Ideally you should be using async/await and forego calls to Task.Run altogether though. This is actually the crux of the issue with your cancellation. You are calling the Task ctor that accepts 2 parameters - action and state. So Token is being passed to the action as the parameter (obj in your action code), not as the cancellation token. The task is still running in the background when you get to the ContinueWith call.

一旦你修复了你实际上没有使用取消令牌的事实你最后一个问题将有AAAA线。在CTS上调用Cancel只会设置令牌被取消的标志。任务可能会也可能不会立即响应。
直到任务看到它应该取消然后中止它不被标记为已取消。所以你有一个竞争条件。很可能你通常会发现AAAA表示没有取消,但有时星星可能排队并且任务在执行之前取消。有
无法知道。因此,您需要等待使用Wait(或结果,如果您想要结果)完成任务。当您调用其中任何一个成员时,他们将等待任务完成,如果任务失败
或被取消,则返回结果或抛出异常。

Once you fix the fact that you aren't actually using the cancellation token the last problem you'll have is with the AAAA line. Calling Cancel on the CTS simply sets the flag that the token is cancelled. The task may or may not respond immediately to it. Until the task sees it should cancel and then aborts it isn't marked as cancelled. So you have a race condition. Most likely you'll generally find AAAA says not cancelled but on occasion the stars may line up and the task cancel before it is executed. There is no way to know. So you need to wait for the task to complete by using Wait (or Result if you want the result). When you call either of these members they will wait for the task to complete and either return the result or throw an exception if the task failed or was cancelled.

这是清理过的你的代码版本的行为符合你的要求。

Here's the cleaned up version of your code that behaves the way you want.

class Program
{
    static void Main ( string[] args )
    {
        TaskExample obj = new TaskExample();
        obj.DoIt();
    }

    public class TaskExample
    {
        CancellationTokenSource CTS = new CancellationTokenSource();
            
        protected void Workingloop ()
        {
            for (int i = 0; i < 100; ++i)
            {
                Console.WriteLine(i);
                Thread.Sleep(1000);

                CTS.Token.ThrowIfCancellationRequested();
            }
        }

        public void DoIt ()
        {
            //Action<object> action = ( object obj ) => {
            //    Workingloop();
            //};

            //Task t = new Task(action, Token);
            //t.Start();
            var t = Task.Run(() => Workingloop(), CTS.Token);
            t.ContinueWith(task => Console.WriteLine(


" BBBB --- Task is cancelled:{t.IsCanceled}"));;

Console.WriteLine("按Enter取消操作");
Console.ReadLine();
Console.WriteLine(" Canceling task ...");
CTS.Cancel();

//需要等待任务完成,否则它可能会或可能不会被
//时间取消到达下一行
try
{
t.Wait();
}抓住
{
if(!t.IsCanceled)
throw;
};

Console.WriteLine(
"BBBB --- Task is canceled: {t.IsCanceled}")); Console.WriteLine("Press Enter to cancel operation"); Console.ReadLine(); Console.WriteLine("Cancelling task..."); CTS.Cancel(); //Need to wait for the task to complete otherwise it may or may not be cancelled by the //time you get to the next line try { t.Wait(); } catch { if (!t.IsCanceled) throw; }; Console.WriteLine(


" AAAA ---任务被取消:{t.IsCanceled}");

Console.ReadLine();
}
}
}
"AAAA --- Task is canceled: {t.IsCanceled}"); Console.ReadLine(); } } }

这是使用async / await的更清晰的方法。

Here's the far cleaner approach using async/await.

class Program
{
    static void Main ( string[] args )
    {
        var cts = new CancellationTokenSource();
            
        var t = DoItAsync(cts.Token);

        Console.WriteLine("Press Enter to cancel operation");
        Console.ReadLine();
        Console.WriteLine("Cancelling task...");
        cts.Cancel();

        //Need to wait for the task to complete otherwise it may or may not be cancelled by the
        //time you get to the next line
        try
        {
            t.Wait();
        } catch
        {
            if (!t.IsCanceled)
                throw;
        };

        Console.WriteLine(


这篇关于任务,线程,工厂,取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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