Learner
Learner

Reputation: 4004

Ideal way of sending multiple files to multiple FTP accounts using multiple threads via windows service?

Windows service needs to send multiple files to multiple FTP folders based on the client id .I have the basic operation working where the timer calls PerformTimerOperation every 5 minutes.

Clients.xml

<clients>
  <client>
    <id>1</id>
    <name>client 1</name>
    <ftp>FTP URL1</ftp>
    <username>FTP USer1</username>
    <password>FTP Pass1</password>
  </client>
  <client>
    <id>2</id>
    <name>client 2</name>
    <ftp>FTP URL2</ftp>
    <username>FTP USer2</username>
    <password>FTP Pass2</password>
  </client>
</clients>

Clients.cs

public class Clients
    {
        public string ClientName { get; set; }
        public string ClientId { get; set; }
        public string FTP { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }

        public Clients()
        {
            ClientName = string.Empty;
            ClientId = string.Empty;
            FTP = string.Empty;
            Username = string.Empty;
            Password = string.Empty;
        }

        public List<Clients> GetClientList()
        {
            List<Clients> result;
            // load data file
            using (XmlTextReader xmlReader = new XmlTextReader("clients.xml"))
            {
                XDocument xdoc = XDocument.Load(xmlReader);

                var Clients = from clientItem in xdoc.Root.Elements()
                              select new Clients
                              {
                                  ClientName = clientItem.Element("name").Value,
                                  ClientId = clientItem.Element("id").Value,
                                  FTP = clientItem.Element("ftp").Value,
                                  Username = clientItem.Element("username").Value,
                                  Password = clientItem.Element("password").Value
                              };

                result = Clients.ToList();
            }
            return result;
        }
    }

ServiceImplementation.cs

    public void OnStart(string[] args)
            {
                System.Threading.Thread.Sleep(1000);
                keepLooping = true;

                //new System.Threading.Thread(PerformTimerOperation).Name = "Thread ";
                new System.Threading.Thread(PerformTimerOperation).Start();
            }


    PerformTimerOperation
            private void PerformTimerOperation(object state)
            {
                while (keepLooping)
                {
                    Clients objClient= new Clients();
                    List<Clients> objClientList = objClient.GetClientList();

                    foreach (var list in objClientList)
                    {
                        ConsoleHarness.WriteToConsole(ConsoleColor.Cyan, list.ClientId);
                        ConsoleHarness.WriteToConsole(ConsoleColor.Cyan, list.ClientName);
                        ConsoleHarness.WriteToConsole(ConsoleColor.Cyan, list.FTP);
                        ConsoleHarness.WriteToConsole(ConsoleColor.Cyan, list.Username);
                        ConsoleHarness.WriteToConsole(ConsoleColor.Cyan, list.Password);

***// Here I would like to call individual client database, get data, convert to XLS and send to appropriate FTP.
// So, if I have 2 clients in the XML file. This loop will call each client one by one and send files to corresponding FTP.
// Is it possible to assign each operation to separate thread so that multiple threads can start sending files to different FTP accounts simultaneously?***

                     }

                    System.Threading.Thread.Sleep(50000);
                }

            }

Best practice and performance is really important. Also, open to constructive criticism with current approach.

Upvotes: 0

Views: 420

Answers (1)

GalacticCowboy
GalacticCowboy

Reputation: 11759

Some notes and suggestions:

  • Use a timer and event subscription instead of thread sleep.
  • Extract the functionality for a client - get list of files, process, send - to a separate method. Method will take the instance of Clients from the current loop iteration.
  • Once it's a separate method, you can spawn a new thread (from the ThreadPool), passing this method name as the thread method and any relevant parameters.
  • Make GetClientList() static so you don't have to instantiate an instance of the class to call it. You'd call Clients.GetClientList() instead.

Note that, in the example on the MSDN site, they use a Thread.Sleep() to simulate thread synchronization. In your case, this isn't necessary since you're running a service - the main thread isn't going to end until you tell it to do so.


Assuming you implement a method such as SendFilesToClient(Clients currentClient), you would queue it something like this:

ThreadPool.QueueUserWorkItem(new WaitCallback(SendFilesToClient), list);

Upvotes: 2

Related Questions