简体   繁体   中英

Writing to files inside of a Task which is created by a foreach loop in C#

So I've come across an interesting issue. I had to write a utility application that hits a webservice to pull down data and write it to a file. The issue is that I have to make multiple concurrent calls to this webservice with different parameters and write the results to different files. Here is the gist of it in pseudo-code...

    var taskList = new List<Task>();
    foreach (string rCode in _config.rCodes) {
        taskList.Add(Task.Factory.StartNew(() =>
        {
            using (TextWriter tw = new StreamWriter(_config.OutputPath + string.Format(@"\{0}-{1}.csv", rCode, DateTime.Now.ToString("yyyy-MM-ddHHmmssfff")), false)) {
                <call webservice and write to the output file using tw.WriteLine>
            }
        }
    }
    Task.WaitAll(taskList.ToArray());

The tasks get created, webservices called, and data is getting written however I'm experiencing a collision of sorts. I'm seeing data meant for one file ending up in another file. I feel like each instance of the TextWriter in each created tasks are fighting with each other but in my mind, shouldn't they not because the scope of the TextWriter is the task that it was created in?

I did some researching and someone recommended doing a Parallel.Foreach but I experienced the same issue. The reason I want to run these concurrently is that the result sets due to our third-party are required every 15 minutes and running in series instead of parallel could push that limit (affecting a public-facing application). Right now, we're OK but in the busier times of year, this could cause an issue when the data sets grow larger.

The problem is that rCode is in the outer scope, making it a global variable for sub-tasks.

To correct it, you can do:

foreach (string rCode in _config.rCodes)
{
    string code = rCode;
    taskList.Add(Task.Factory.StartNew(() =>
    {
        using (TextWriter tw = new StreamWriter(_config.OutputPath + string.Format(@"\{0}-{1}.csv", code, DateTime.Now.ToString("yyyy-MM-ddHHmmssfff")), false)) {
            // ...
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM