c# - 如何跟踪循环中完成了多少异步任务?

标签 c# multithreading c#-4.0 task-parallel-library task

我有一些代码循环遍历记录列表,为每个记录启动一个导出任务,并在每次任务完成时将进度计数器增加 1,以便用户知道该过程进行了多长时间。

但根据循环的时间安排,我经常会看到输出显示较高的数字在较低的数字之前。

例如,我希望看到这样的输出:

Exporting A
Exporting B
Exporting C
Exporting D
Exporting E
Finished 1 / 5
Finished 2 / 5
Finished 3 / 5
Finished 4 / 5
Finished 5 / 5

But instead I get output like this

Exporting A
Exporting B
Exporting C
Exporting D
Exporting E
Finished 1 / 5
Finished 2 / 5
Finished 5 / 5
Finished 4 / 5
Finished 3 / 5

I don't expect the output to be exact since I'm not locking the value when I update/use it (sometimes it outputs the same number twice, or skips a number), however I wouldn't expect it to go backwards.

My test data set is 72 values, and the relevant code looks like this:

var tasks = new List<Task>();
int counter = 0;

StatusMessage = string.Format("Exporting 0 / {0}", count);

foreach (var value in myValues)
{
    var valueParam = value;

    // Create async task, start it, and store the task in a list
    // so we can wait for all tasks to finish at the end
    tasks.Add(
        Task.Factory.StartNew(() =>
        {
            Debug.WriteLine("Exporting " + valueParam );

            System.Threading.Thread.Sleep(500);
            counter++;
            StatusMessage = string.Format("Exporting {0} / {1}", counter, count);

            Debug.WriteLine("Finished " + counter.ToString());
        })
    );
}

// Begin async task to wait for all tasks to finish and update output
Task.Factory.StartNew(() =>
{
    Task.WaitAll(tasks.ToArray());
    StatusMessage = "Finished";
});

输出可以在调试语句和 StatusMessage 输出中向后出现。

正确的方法是什么来计算一个循环中完成了多少个异步任务,这样这个问题就不会发生?

最佳答案

您会得到混合输出,因为计数器的递增顺序与 Debug.WriteLine(...) 方法的执行顺序不同。

要获得一致的进度报告,可以在任务中引入报告锁

tasks.Add(
    Task.Factory.StartNew(() =>
    {
        Debug.WriteLine("Exporting " + valueParam );

        System.Threading.Thread.Sleep(500);
        lock(progressReportLock)
        {
           counter++;
           StatusMessage = string.Format("Exporting {0} / {1}", counter, count);
           Debug.WriteLine("Finished " + counter.ToString());
        }
    })
);

关于c# - 如何跟踪循环中完成了多少异步任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15745567/

相关文章:

c# - Entity Framework 从存储过程返回列表

python - python中的线程使用队列

Android如何实现从runnable执行异步任务

c# - 无法从 App.config 引用变量

c# - lock() 是否保证按请求的顺序获取?

c# - 使用 COM 对象从 C# 调用 Matlab

java - 在什么情况下其他线程看不到对非 volatile 变量的写入?我可以出于实验目的强制这样的条件吗?

c#-4.0 - 使用动态关键字调用子类方法

asp.net - 刷新/重新绑定(bind)一个下拉列表 asp.net MVC

c# - 无法将类型为 'Newtonsoft.Json.Linq.JArray' 的对象转换为类型 'System.Collections.Generic.List`