RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1439635
Accepted
Сергей
Сергей
Asked:2022-08-16 03:57:44 +0000 UTC2022-08-16 03:57:44 +0000 UTC 2022-08-16 03:57:44 +0000 UTC

如果至少有一个任务结束,如何关闭所有任务

  • 772

有decimal一个参数。假设它等于 10。有Task一段时间100ms将它减少0.1. 一旦参数变得等于1,任务应该结束并且参数不应该再减少。如果Task只有一个,则可以正常工作。但如果它们是2, 3, 100...,那么参数最终会变小1。我尝试使用CancellationToken来完成所有任务,但结果还是一样。我的代码:

    class Program
    {
        static decimal param = 108;
        static CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
        static CancellationToken token;

        static void Main(string[] args)
        {
            int tasksCount = 16;
            token = cancelTokenSource.Token;

            Console.WriteLine("Start Param = {0}", param);
            Console.WriteLine("Tasks Count = {0}", tasksCount);

            var tasksList = new List<Task>();
            for (var i = 0; i < tasksCount; i++)
            {
                Task task = new Task(Decrementation, token);
                tasksList.Add(task);
            }
            tasksList.ForEach(x => x.Start());
            Task.WaitAny(tasksList.ToArray());

            Console.WriteLine("Result = {0}", param);
            Console.Read();
        }

        private static void Decrementation()
        {
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                if (CanTakeMore())
                {
                    Task.Delay(100);
                    param = param - 0.1m;
                }
                else
                {
                    cancelTokenSource.Cancel();
                    return;
                }
            }
        }

        private static bool CanTakeMore()
        {
            if (param > 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

输出不同,但始终小于 1。

在此处输入图像描述

我究竟做错了什么?

c# .net
  • 1 1 个回答
  • 45 Views

1 个回答

  • Voted
  1. Best Answer
    aepot
    2022-08-16T07:00:02Z2022-08-16T07:00:02Z

    结论不一样

    由于此代码不是线程安全的,因此必须在幕后进行减法和值检查。

    • Task.Delay没有就行不通await
    • Task根本不应该使用构造函数,这是创建任务的过时方法
    • CancellationTokenSource这IDisposable是要使用的using
    • 避免多线程中的全局资源、字段和属性,使用方法参数和返回值
    • 使用同步组合器WaitAny也不WaitAll值得,还有异步

    让我们添加一些线程安全性。如果一切都正确完成,甚至不需要取消令牌,如果所有方法本身都安全完成,则无需安排黄油。

    class Program
    {
        static decimal param = 108;
        static readonly object syncRoot = new object();
    
        static asynс Task Main(string[] args)
        {
            int tasksCount = 16;
    
            Console.WriteLine($"Start Param = {param}");
            Console.WriteLine($"Tasks Count = {tasksCount}");
            
            var tasks = new List<Task>();
            for (int i = 0; i < tasksCount; i++)
            {
                Task task = Task.Run(Decrementation);
                tasks.Add(task);
            }
                
            await Task.WhenAll(tasks);
    
            Console.WriteLine($"Result = {param}");
            Console.ReadKey();
        }
    
        private static void Decrementation()
        {
            while (true)
            {
                lock (syncRoot)
                {
                    if (CanTakeMore()) 
                        param -= 0.1m;
                    else
                        return;
                }
                Thread.Sleep(100); // здесь бы имел смысл токен отмены и await Task.Delay, если бы ожидание было длительным
                                   // напишите коммент, нсли надо показать асинхронный код с отменой
            }
        }
    
        private static bool CanTakeMore()
        {
            return param > 1;
        }
    }
    
    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5