2017-08-19 30 views
0

我有数以千计的文件位于FTP服务器。我的任务是从ftpserver下载文件,然后解压缩文件,然后处理文件。对于下载我使用Tamir库和解压缩我使用Ionic.zip然后处理文件。如何通过在c#中使用线程来加紧工作?

当我使用的线程,下载从FTP服务器的文件停止,不知道其中的原因,也许FTP服务器不允许使用线程下载文件。然后我使用线程来解压缩文件并进行处理。这也因为错误而失败,如

进程无法访问文件'文件',因为它正在被另一个进程使用。

所以现在我正在依次做的一切。代码原型如下图所示

static void Main(string[] args) 
     { 
      string FTPpah = "d://Testpath"; 
      DonloadUnzipProcessFile(FTPpah); 
     } 

     private static void DonloadUnzipProcessFile(string FTPpah) 
     { 
      string Localpath = @"e://testpath"; 
      //Using Tamir libraryr 
      DownloadFile(FTPpah,Localpath); 
      //Ionic.zip library 
      UnzipFile(Localpath); 
      //c#code 
      ProcessFile(Localpath); 
     } 

有没有什么办法可以提高使用ThreadsProcess这项任务?

编辑

从FTP服务器上下载不能用线程来完成?如果是这样,我想通过使用任务解压缩和处理。因此,我将创建10个任务(TPL),每个任务需要10个文件并解压缩,然后执行10个任务,这样的情况有可能吗?

+2

搜索TPL数据流 –

+2

塔米尔/ SharpSSH库是SFTP库,而不是一个FTP库。这是完全不同的东西+这是一个死了的项目,不会维持多年。不要使用它! –

+2

异步等待是要走的路,这样的IO操作,不得在线程完成,会降低系统的可扩展性 –

回答

2

继必是你的代码来创建异步版本,它可以做后台文件下载。你可以做1000个文件,它永远不会堵塞系统,会有非常高的吞吐量,因为一切都会发生在后台,并且会非常快。

async Task Main() 
{ 
    // List of FTP Path and Local file Path for processing 
    var ftpFilesForProcessing = new Dictionary<string, string> 
    { 
     {"Ftp_Path_1","Local_Path_1"}, 
     {"Ftp_Path_2","Local_Path_2"}, 
     {"Ftp_Path_3","Local_Path_3"}, 
    }; 

    // FTP Files with Task for Async processing 
    var ftpFilesTaskForProcessing = new Dictionary<string, Task<string>>(); 

    // Add a relevant Task to each file processing 
    foreach (var file in ftpFilesForProcessing) 
     ftpFilesTaskForProcessing[file.Key] = FtpRead(file.Key,file.Value); 

    // All the FTP downloads will be processed here Asynchronously, then it 
     will proceed with the remaining logic 
    await Task.WhenAll(ftpFilesTaskForProcessing.Values); 

    // Unzip All files Asynchronously 

    // Process Data using Task Parallel Library  
} 

// Read the Ftp file to a local file 
public async Task<string> FtpRead(string ftpPath, string localPath) 
{ 
    // Create FTP Request object 
    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpPath); 

    // Set FTP Request Object properties 
    ftpRequest.KeepAlive = false; 
    ftpRequest.UseBinary = true; 
    ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile; 

    // This example assumes the FTP site uses anonymous logon. 
    ftpRequest.Credentials = new NetworkCredential("<Username>", "<Password>"); 

    var ftpWebResponse = await ftpRequest.GetResponseAsync(); 

    Stream ftpResponseStream = ((FtpWebResponse)ftpWebResponse).GetResponseStream(); 

    StreamReader ftpStreamReader = new StreamReader(ftpResponseStream); 

    StreamWriter ftpStreamWriter = new StreamWriter(localPath); 

    var fileData = await ftpStreamReader.ReadToEndAsync(); 

    await ftpStreamWriter.WriteAsync(fileData); 

    ftpStreamReader.Close(); 
    ftpResponseStream.Close(); 

    return localPath; 
} 
+0

我会对此进行研发 – peter

2

首先,任务不一定是线程。 (What is the difference between task and thread?

其次,我不会推荐使用线程,但TasksParallel.Foreach,因为他们有自己的优化,除非你有一些非常具体的东西通过线程实现。

对于您的情况,我会做到这一点:创建一个类ProcessFile将下载,解压缩,处理一个文件,并触发事件;有一个n(比如10)ProcessFile的Enumerable/List列表;将管理这些ProcessFile的类将通过添加新实例来对事件作出反应,以便保持正在处理的活动文件的n

好运

相关问题