C# 通过windows服务使用多个线程将多个文件发送到多个FTP帐户的理想方式?

C# 通过windows服务使用多个线程将多个文件发送到多个FTP帐户的理想方式?,c#,multithreading,windows-services,C#,Multithreading,Windows Services,Windows服务需要根据客户端id将多个文件发送到多个FTP文件夹。我的基本操作是计时器每5分钟调用一次PerformTime属性 Clients.xml <clients> <client> <id>1</id> <name>client 1</name> <ftp>FTP URL1</ftp> <username>FTP USer1</use

Windows服务需要根据客户端id将多个文件发送到多个FTP文件夹。我的基本操作是计时器每5分钟调用一次PerformTime属性

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>

1.
客户1
FTP URL1
FTP用户1
FTP密码1
2.
客户2
FTP URL2
FTP用户2
FTP密码2
客户端.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;
        }
    }
    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);
                }

            }
公共类客户端
{
公共字符串ClientName{get;set;}
公共字符串ClientId{get;set;}
公共字符串FTP{get;set;}
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公众客户()
{
ClientName=string.Empty;
ClientId=string.Empty;
FTP=string.Empty;
Username=string.Empty;
Password=string.Empty;
}
公共列表GetClientList()
{
列出结果;
//加载数据文件
使用(XmlTextReader=newxmltextreader(“clients.xml”))
{
XDocument xdoc=XDocument.Load(xmlReader);
var Clients=来自xdoc.Root.Elements()中的clientItem
选择新客户
{
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
};
结果=Clients.ToList();
}
返回结果;
}
}
ServiceImplementation.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;
        }
    }
    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);
                }

            }
public void OnStart(字符串[]args)
{
系统线程线程睡眠(1000);
keeploping=true;
//新系统.Threading.Thread(performtimeropertion).Name=“Thread”;
新系统.Threading.Thread(performtimeropertion.Start();
}
性能时效
私有void性能时间属性(对象状态)
{
同时(继续)
{
Clients objClient=新客户端();
List objClientList=objClient.GetClientList();
foreach(ObjClient列表中的变量列表)
{
ConsoleWarness.WriteToConsole(ConsoleColor.Cyan,list.ClientId);
ConsoleWarness.WriteToConsole(ConsoleColor.Cyan,list.ClientName);
ConsoleWarness.WriteToConsole(ConsoleColor.Cyan,list.FTP);
ConsoleWarness.WriteToConsole(ConsoleColor.Cyan,list.Username);
ConsoleWarness.WriteToConsole(ConsoleColor.Cyan,list.Password);
***//在这里,我想调用个人客户端数据库,获取数据,转换为XLS并发送到适当的FTP。
//因此,如果XML文件中有两个客户端,这个循环将逐个调用每个客户端,并将文件发送到相应的FTP。
//是否可以将每个操作分配给单独的线程,以便多个线程可以同时向不同的FTP帐户发送文件***
}
系统。线程。线程。睡眠(50000);
}
}
最佳实践和性能非常重要。
此外,对当前方法的建设性批评持开放态度。

一些注意事项和建议:

  • 使用线程睡眠代替线程睡眠。
  • 提取客户端的功能-获取文件列表、处理、发送-到单独的方法。方法将从当前循环迭代中获取
    客户机的实例
  • 一旦它是一个单独的方法,您就可以将此方法名作为线程方法和任何相关参数传递
  • 将GetClientList()设为静态,这样就不必实例化类的实例来调用它。您可以调用
    Clients.GetClientList()
注意,在MSDN站点的示例中,他们使用
Thread.Sleep()
来模拟线程同步。在您的情况下,这是没有必要的,因为您正在运行一个服务-主线程不会结束,除非您告诉它这样做


假设您实现了一种方法,例如
SendFilesToClient(Clients currentClient)
,您将按照如下方式对其进行排队:

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

它如何确定哪些文件属于/转到特定客户端?基于list.ClientId。客户端id通常是数据库名称@Galaxicok,那么它是从数据库中获取文件列表的吗?您正在休眠主(服务)线程,这意味着它无法在休眠时正确响应系统事件。这是一个捏造的例子,因为系统可能会终止它,但是考虑一个触发的情况,然后睡觉5分钟。30秒后,您希望重新启动系统。再过4:30,服务就不会收到“停止”命令了。谢谢@Galactic收到了。可能的话,您可以发布一段代码来实现与我的代码相关的ThreadPool.QueueUserWorkItem。我是这类项目的新手,如果你能帮我编写代码,我将不胜感激。可能的,最后一个问题:您能告诉我在进程方面会发生什么情况(即,一个队列是将一个接一个地向多个客户端发送文件,还是多个线程将执行发送文件的任务)。我只想能够可视化线程向FTP发送文件的过程。这样做,每个队列将完全独立运行-每个线程将