Multithreading Throws Files Is In Use Excepton

SiamIT

Active member
Joined
Aug 3, 2021
Messages
40
Programming Experience
5-10
Greetings..

i am using following codes to run multiple threads at a time to get data from different links and save the data to different file as well. As the file name/path is different for each loop? i don't understand why it throws following exception:

The process cannot access the file 'full file path' because it is being used by another process.

here is my code:

C#:
        private async Task ProcessGameList(List<string> lRGameList, ExcelWorksheet oRSheet, int CurRowNum, string CurrentYear, int CurrentWeek, string FileInUse)
        {
            string sXML, sMessage, sFilePath;
            List<Task> lTaskList;
            Task tCurTask;
            int LastProcessed;

            lTaskList = new List<Task>();
            LastProcessed = 0;
            for (int iGameLoop = 0; iGameLoop < lRGameList.Count; iGameLoop++)
            {
                sFilePath = string.Format(@"{0}\Data\Game-{1}-{2}-{3}.xml", sAPPPath, CurrentYear, (CurrentWeek + 1), (iGameLoop + 1));
                if (File.Exists(sFilePath))
                {
                    continue;
                }
                tCurTask = new Task(() => CrawllGameData(lRGameList[iGameLoop], sFilePath));
                tCurTask.Start();
                lTaskList.Add(tCurTask);
                if(lTaskList.Count == 7 || iGameLoop == (lRGameList.Count - 1))
                {
                    sMessage = $"Downloading Game Data For Weeek {(CurrentWeek + 1)}  Game {LastProcessed + 1} - {iGameLoop + 1}...";
                    this.Text = sMessage;
                    await Task.WhenAll(lTaskList.ToArray());
                    lTaskList.Clear();
                    LastProcessed = iGameLoop;
                }
            }
        }

        private void CrawllGameData(string URL, string sFilePath)
        {
            string sHTML, sXML;

            //MessageBox.Show(URL);
            sHTML = fGetHTML(URL);
            File.WriteAllText(Path.ChangeExtension(sFilePath, ".html"), sHTML);
            sXML = fHtml2Xml(sHTML);
            File.WriteAllText(sFilePath, sXML);
        }

Note: the exception throws at different loop each time..

best regards
 
Last edited:
Solution
@SiamIT: The local variable need to be declared and set within the loop. This is why I first posted that you needed to read about lambda captures. If you took time to read about them, you would have learned why this is so. Instead, you refactored the code to do the declaration outside the loop, and put setting within the loop which just places you in the same situation all over again.
The error is self-explanatory. There's another process that has a lock on the file while it is doing work on it. It's also possible you are locking the file yourself in one of your other threads.
 
The error is self-explanatory. There's another process that has a lock on the file while it is doing work on it. It's also possible you are locking the file yourself in one of your other threads.
i am sorry.. but did you get my first line of message? or may be not due to my bad English? i have told none of the threads using same file as file name is changed my the number of loop. then how can two threads can access the same file? because different file name is passed to each threads..

am i clear now ? or still not sir?
 
Try this simplified code to see the problem:
C#:
for (int iGameLoop = 0; iGameLoop < 10; iGameLoop++)
{
    Task.Run(() => Debug.WriteLine(iGameLoop));    
}
To fix, assign iGameLoop to a temporary variable inside the loop and use that as input for the Task.
 
To fix, assign iGameLoop to a temporary variable inside the loop and use that as input for the Task.

thanks for your reply sir, i have tried following, but fails:

C#:
            for (int iGameLoop = 0; iGameLoop < lRGameList.Count; iGameLoop++)
            {
                CurIndex = iGameLoop;
                sFilePath = string.Format(@"{0}\Data\Game-{1}-{2}-{3}.xml", sAPPPath, CurrentYear, (CurrentWeek + 1), (CurIndex + 1));
                if (File.Exists(sFilePath))
                {
                    continue;
                }
                tCurTask = new Task(() => CrawllGameData(lRGameList[CurIndex], sFilePath));
                tCurTask.Start();
                lTaskList.Add(tCurTask);
                if (lTaskList.Count == 7 || CurIndex == (lRGameList.Count - 1))
                {
                    sMessage = $"Downloading Game Data For Weeek {(CurrentWeek + 1)}  Game {LastProcessed + 1} - {CurIndex + 1}...";
                    this.Text = sMessage;
                    await Task.WhenAll(lTaskList.ToArray());
                    lTaskList.Clear();
                    LastProcessed = CurIndex + 1;
                }
            }
[Code]
 
that should be:
C#:
var CurIndex = iGameLoop;
 
You can't do that, this variable must be inside the loop.
 
@SiamIT: The local variable need to be declared and set within the loop. This is why I first posted that you needed to read about lambda captures. If you took time to read about them, you would have learned why this is so. Instead, you refactored the code to do the declaration outside the loop, and put setting within the loop which just places you in the same situation all over again.
 
Solution
You can't do that, this variable must be inside the loop.
Of course i can sir, i just needed a helping hand. You did the help at first but.. however, thanks again for your help..

@SiamIT: The local variable need to be declared and set within the loop. This is why I first posted that you needed to read about lambda captures. If you took time to read about them, you would have learned why this is so. Instead, you refactored the code to do the declaration outside the loop, and put setting within the loop which just places you in the same situation all over again.

thanks a lot sir @Skydiver , that's what i was looking for, just a clarification for the issue and how to overcome. I i did checked the link, however, that was gone over my head. but now i got. Once again thanks. I am in real debt with you.
 
Back
Top Bottom