2016-07-22 11 views
0

Ich möchte Ihre Hilfe bei der Implementierung von Multi-Threading in meinem C# -Programm suchen.C# Multi-Threading - Upload auf FTP-Server

Das Programm zielt darauf ab, 10.000 ++ Dateien auf einen FTP-Server hochzuladen. Ich plane mindestens ein Minimum von 10 Threads zu implementieren, um die Geschwindigkeit des Prozesses zu erhöhen.

Damit ist das die Codezeile, die ich habe:

I 10 Threads initialisiert:

public ThreadStart[] threadstart = new ThreadStart[10]; 
public Thread[] thread = new Thread[10]; 

Mein Plan ist, eine Datei zu einem Thread zugewiesen werden, wie folgt:

file 1 > thread 1 
file 2 > thread 2 
file 3 > thread 3 
. 
. 
. 
file 10 > thread 10 
file 11 > thread 1 
. 
. 
. 

Und so habe ich folgendes:

foreach (string file in files) 
{ 
    loop++; 

    threadstart[loop] = new ThreadStart(() => ftp.uploadToFTP(uploadPath + @"/" + Path.GetFileName(file), file)); 
    thread[loop] = new Thread(threadstart[loop]); 
    thread[loop].Start(); 

    if (loop == 9) 
    { 
     loop = 0; 
    }       
} 

Die Übergabe von Dateien an die entsprechenden Threads funktioniert. Mein Problem ist, dass der Beginn des Threads sich überschneidet.

Ein Beispiel für Ausnahme ist, dass wenn Thread 1 ausgeführt wird, eine Datei an es übergeben wird. Es wird ein Fehler zurückgegeben, da Thread 1 noch nicht erfolgreich ausgeführt wurde und dann ein neuer Parameter an ihn übergeben wird. Trifft auch auf andere Threads zu.

Was ist der beste Weg, dies zu implementieren?

Jede Rückmeldung wird sehr geschätzt. Vielen Dank! :)

+0

Sie die TPL nutzen könnten und lassen Sie die 'SynchronisationContext' die Menge an Themen behandeln Sie erstellen können .... –

+0

... oder' TaskSchedular' .... –

+1

Da dies ein netzwerkbezogenes Problem ist, sollten Sie mindestens 'async/await' für IOCP-Groovness verwenden. Viel besser als das Hochfahren von Threads, die bei einer Netzwerkoperation nur blockiert werden. Vielleicht möchten Sie sogar _TPL Dataflow_ zumindest solange berücksichtigen, bis Ihre Netzwerkbandbreite sich verflacht – MickyD

Antwort

1

Mit Asynchron-await und nur eine Reihe von Dateien in es passieren:

private static async void TestFtpAsync(string userName, string password, string ftpBaseUri, 
     IEnumerable<string> fileNames) 
    { 
     var tasks = new List<Task<byte[]>>(); 
     foreach (var fileInfo in fileNames.Select(fileName => new FileInfo(fileName))) 
     { 
     using (var webClient = new WebClient()) 
     { 
      webClient.Credentials = new NetworkCredential(userName, password); 
      tasks.Add(webClient.UploadFileTaskAsync(ftpBaseUri + fileInfo.Name, fileInfo.FullName)); 
     } 
     } 
     Console.WriteLine("Uploading..."); 
     foreach (var task in tasks) 
     { 
     try 
     { 
      await task; 
      Console.WriteLine("Success"); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
     } 
    } 

Dann es so nennen:

const string userName = "username"; 
    const string password = "password"; 
    const string ftpBaseUri = "ftp://192.168.1.1/"; 
    var fileNames = new[] { @"d:\file0.txt", @"d:\file1.txt", @"d:\file2.txt" }; 
    TestFtpAsync(userName, password, ftpBaseUri, fileNames); 
+0

Diese Lösung funktionierte für mich. Vielen Dank! – kevingerard

0

Warum es auf die harte Art und Weise zu tun? .net hat bereits eine Klasse namens ThreadPool. Sie können nur verwenden, und es verwaltet die Threads selbst. Ihr Code wird so aussehen:

static void DoSomething(object n) 
    { 
     Console.WriteLine(n); 
     Thread.Sleep(10); 
    } 

    static void Main(string[] args) 
    { 
     ThreadPool.SetMaxThreads(20, 10); 
     for (int x = 0; x < 30; x++) 
     { 
      ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomething), x); 
     } 
     Console.Read(); 
    } 
+1

Der einzige Nachteil bei der Verwendung des 'ThreadPool' ist, dass Sie alle Jobs verfolgen müssen, um festzustellen, wann sie fertig sind. Sie könnten stattdessen 'Parallel.ForEach' verwenden, was das für Sie erledigt. –