【问题标题】:Counter inside asynchronous functions异步函数内的计数器
【发布时间】:2018-11-27 10:24:27
【问题描述】:

我正在尝试实现一个多重下载功能,它会同时触发和下载 10 个文件。

我也实现了 IProgress 接口,让我知道它的进展情况。

我现在需要的是一个简单的计数器在他们每个人里面说:这是下载#1,这是下载#2,等等。

我不能做一个普通的计数器,因为它们可能同时运行并在我使用/存储值之前更新计数器,导致我的值错误或其中许多值相同。

我已经研究了 Interlocked 类,但我只是找不到合适的实现,它会为每个触发的异步动态函数存储一个特定的数字。

我使用数字将进度存储在一个数组中,所以我会这样调用:

IProgress<double> progressHandler = new Progress<double>(p => HandleUnitProgressBar(p, downloadIndex));

并让处理程序将进度存储在数组的指定单元格中。

谁能指出我正确的方向?

编辑 #1:添加我正在尝试使用的代码:

for (int i = 0; i < _downloadList.Count; i++)
            {
                var url = _downloadList.ToArray()[i];
                Task.Factory.StartNew
                (
                    async () =>
                    {
                        try
                        {
                            MegaApiClient client = new MegaApiClient();
                            //client.LoginAnonymous();
                            downloadIndex = i;

                            IProgress<double> progressHandler = new Progress<double>(p => HandleUnitProgressBar(p, downloadIndex));

                            await client.DownloadFileAsync(fileLink, url.Value, progressHandler);
                        }
                        catch (Exception e)
                        {
                            //will add later
                        }
                    }
                , CancellationToken.None
                , TaskCreationOptions.None
                , TaskScheduler.Current
            );
        }

此代码的问题在于,当它到达 downloadIndex = i 时,i 已经是 4(对于 4 个同时下载),而我想向所有处理程序发送 0、1、2、3 而不是 4。

【问题讨论】:

    标签: c# asynchronous task progress class-variables


    【解决方案1】:

    我不知道我是否完全理解你的问题,但我会试一试。如果我理解正确,您是在要求为请求分配一个整数以进行跟踪,对吗?我之前做过一些压力测试,并以 100 波的形式发送请求。代码看起来有点像这样:

        static void Main(string[] args)
        {
            var app = new Program();
            var i = 0;
            var j = 0;
            var tasks = new List<Task>();
    
            while (j < 1000)
            {
                tasks.Add(app.CreateOpp(j));
                Console.WriteLine(i);
                if (i == 100)
                {
                    var done = Task.WhenAll(tasks);
                    done.Wait();
                    i = 0;
                    tasks = new List<Task>();
                }
    
                i++;
                j++;
            }
        }
    
            private async Task CreateOpp(int i)
        {
            var client = new RestClient("https...");
            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", "Bearer Token");
            request.AddHeader("Content-Type", "application/json");
            var response = await client.ExecuteTaskAsync(request);
    
            Console.WriteLine(i + " Status: " + response.StatusCode);
    
            Console.WriteLine();
        }
    

    在每个任务完成后,与其像我在“Console.WriteLine(i + " Status: " + response.StatusCode);" 行中那样让它写入控制台,您可能只需增加一些值.希望这对您有所帮助,或者至少引导您走上新的道路!

    【讨论】:

    • 为我的目的工作。我在上面添加了一个代码来展示我是如何使用它的。这显然是错误的做法。我将异步方法分离成它自己的方法,删除了所有的 Task.Factory 调用,我刚刚创建了一个异步函数,它接受 url 和索引(如 ur j 所示),它可以 100% 地按照我的需要工作。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2018-11-17
    • 1970-01-01
    • 2021-02-23
    • 1970-01-01
    相关资源
    最近更新 更多