如何在c#中使用线程来加固工作?

时间:2017-08-19 06:36:56

标签: c# .net multithreading ftp console-application

我有数千个文件位于FTP服务器中。我的任务是从ftpserver下载文件,然后解压缩文件,然后处理文件。下载时我正在使用Tamir库并解压缩我正在使用Ionic.zip然后处理文件。

当我使用线程时,从FTP服务器下载文件停止,不知道原因,也许FTP服务器不允许使用线程下载文件。然后我只使用线程解压缩文件和进行处理。这也失败了,如

之类的错误
  

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

所以现在我按顺序做所有事情。代码原型如下所示

 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 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:2)

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

其次,我不建议使用线程,但是TasksParallel.Foreach,因为它们有自己的优化,除非你有通过线程实现非常具体的东西。

对于您的场景,我会这样做:创建一个类ProcessFile,它将下载,解压缩,处理一个文件,并触发一个事件;拥有nProcessFile(例如10个)实例的可枚举/列表;管理这些ProcessFile的类会通过添加新实例来对事件做出反应,以便您处理n个活动文件。

祝你好运