Reputation: 113
I'm working on making a patcher for my game. The patcher checks the size each file on the ftp server with the local file on the user's computer and if it is different, downloads the new file from the ftp server.
I want to add a print message saying "Update complete! X files updated." when it has checked all files but do I know when the function has ended everywhere?
private void CheckForUpdates(string ftpPath, string localPath)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath);
request.Credentials = new NetworkCredential(ftpUser, ftpPass);
request.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
List<string> files = new List<string>();
string line = reader.ReadLine();
while (!string.IsNullOrEmpty(line))
{
if (line != "." && line != ".." && line != ".htaccess")
{
files.Add(line);
}
line = reader.ReadLine();
}
response.Close();
responseStream.Close();
reader.Close();
foreach (string file in files)
{
string newFtpPath = ftpPath + "/" + file;
string newLocalPath = localPath + "/" + file;
new Thread(() => AppendText("Checking " + newLocalPath + Environment.NewLine)).Start();
if (IsFile(newFtpPath))
{
if (File.Exists(newLocalPath))
{
if (!IsFileEqual(newFtpPath, newLocalPath))
{
new Thread(() => AppendText(file + " is out of date or corrupted. Patching in progress..." + Environment.NewLine)).Start();
new Thread(() => Download(newFtpPath, newLocalPath)).Start();
}
}
else
{
new Thread(() => AppendText(file + " is missing. Patching in progress..." + Environment.NewLine)).Start();
new Thread(() => Download(newFtpPath, newLocalPath)).Start();
}
}
else
{
if (!Directory.Exists(newLocalPath))
{
new Thread(() => AppendText(file + " is missing. Patching in progress..." + Environment.NewLine)).Start();
Directory.CreateDirectory(newLocalPath);
}
new Thread(() => CheckForUpdates(newFtpPath, newLocalPath)).Start();
}
}
}
Upvotes: 1
Views: 1174
Reputation: 113
Ok so I fixed the problem by adding a thread count.
Your issue here I see is that you're spawning off new threads. I would definitely be keeping a track of how many threads you are creating and using something like semaphore to control that
When I needed to go deeper into the files add to thread count
threadCount++;
new Thread(() => CheckForUpdates(newFtpPath, newLocalPath)).Start();
And at the end of the function check if there is only 1 thread
if(threadCount == 1)
//print end message
else
threadCount--;
Thanks for the help guys!
Upvotes: 2
Reputation: 12191
That depends; if all you're doing is printing the one method then it's probably not important that its be known everywhere.
If, however, you want other things to happen (or you're likely to want other things to happen in the future) you can always raise an event. This is actually a fairly common pattern, especially if it's an asynchronous operation (and it sounds like it would make sense for it to be one given that it's a potentially long-running task).
If you're using Task Parallelism this can actually help you out with knowing when it's complete (at least for the caller).
Your other problem will be knowing when the threads you're creating are done (because otherwise even if you're running the method as a whole synchronously the fact that it returned doesn't guarantee that all of the threads are done with their work). This, of course, depends on what you mean by "done" - if by "done" you mean "the method has returned control to its caller and all of the associated work is complete" or just "the method has returned control to its caller." (In other words, can the method be considered "done" if some of the threads it created are still downloading files? If you're counting on these to be finished by the time that the method has returned control to its caller this would be a classic race condition).
You can use Task Parallelism to help you out with knowing if the threads are done if you'd like. Another (kind of dumb but effective) way is to keep some kind of variable (to be updated in a thread-safe way) of "running threads" - every time you spawn a new thread you increment the count in a thread-safe way and every time one of them completes it decrements the count (again in a thread-safe way). (If you're not using a Task you could also consider using the Thread Pool for these task for performance reasons rather than creating a new thread every time).
Upvotes: 1