2009-12-21 3 views
0

J'utilise l'objet TcpClient pour transférer les fichiers. Il n'y a qu'un seul objet. Ainsi, lors du transfert du fichier, j'ai utilisé pour verrouiller cet objet et transférer le fichier afin que les autres threads attendent jusqu'à ce que TCPClient soit libéré.Création de threads en parallèle dans C#

Y a-t-il un moyen de faire en sorte que Threads fonctionne en parallèle avec un seul objet?

Répondre

3

Non, assurez-vous que chaque thread utilise sa propre connexion.

+0

tcpclient.connect (remotehost, port) si j'envoie le port autre que l'on utilise pour la fabrication connexion alors il lance une erreur (refus de connexion) en faisant avec le même port, le rend même objet. – marshalprince

+0

Mais si vous utilisez une connexion, comment le serveur saura-t-il quelles données appartiennent ensemble? –

+0

ce que je fais est, pour faire une connexion j'utilise un TCPClient et pour lequel j'envoie \ recevoir le fichier que je crée un autre TCPClient mais maintenant je dois verrouiller le premier i.e utilisé pour la connexion. Mais entre les deux si j'ai besoin d'envoyer les données avec un autre thread (je fais un nouveau TCPClient pour les données) mais pour la connexion TCPClient est déjà verrouillé. Alors, comment puis-je envoyer un autre fichier – marshalprince

0

un peu ....

vous pouvez utiliser NetworkStream.BeginWrite il se sentira comme si vous l'utilisez dans paeallel ....

0

BeginWrite/BeginRead libérera votre thread en cours et faire des choses dans l'arrière-plan. Vous pouvez mettre en file d'attente plusieurs écritures avec BeginWrite (et avoir une idée du travail parallèle). Je ne le recommanderais pas, car le tampon de socket interne peut être plein lors de l'envoi de fichiers.

Vous pouvez toujours passer à un socket et utiliser la méthode SendFile.

Si vous avez plusieurs TcpClient ou Sockets, vous pouvez utiliser les méthodes BeginWrite/BeginRead pour les gérer sans avoir à créer un nouveau thread pour chacun d'entre eux. Ci-dessous un petit exemple qui se connecte au serveur, envoie un fichier et se déconnecte. Il peut gérer n'importe quelle quantité de clients tcp ouverts. Et comme vous le voyez, il n'utilise pas de fils (il est fait en arrière-plan par framework .Net)

/// <summary> 
/// Thread safe queue of client ids 
/// </summary> 
internal class FileSender 
{ 
    /// <summary> 
    /// A write operation have completed 
    /// </summary> 
    /// <param name="ar"></param> 
    private void OnWriteCompleted(IAsyncResult ar) 
    { 
     // We passed the context to this method, cast it back 
     var context = (ClientContext) ar.AsyncState; 

     // end the write 
     context.TcpClient.GetStream().EndWrite(ar); 

     // we've completed. 
     if (context.BytesSent >= context.FileStream.Length) 
     { 
      // notify any listener 
      Completed(this, new CompletedEventArgs(context.RemoteEndPoint, context.FileStream.Name)); 
      context.TcpClient.Close(); 
      return; 
     } 

     // Send more data from the file to the server. 
     int bytesRead = context.FileStream.Read(context.Buffer, 0, context.Buffer.Length); 
     context.BytesSent += bytesRead; 
     context.TcpClient.GetStream().BeginWrite(context.Buffer, 0, bytesRead, OnWriteCompleted, context); 
    } 

    /// <summary> 
    /// Send a file 
    /// </summary> 
    /// <param name="endPoint"></param> 
    /// <param name="fullPath"></param> 
    public void SendFile(IPEndPoint endPoint, string fullPath) 
    { 
     // Open a stream to the file 
     var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read); 

     // Create a client and connect to remote end 
     var client = new TcpClient(); 
     client.Connect(endPoint); 

     // Context is used to keep track of this client 
     var context = new ClientContext 
          { 
           Buffer = new byte[65535], 
           FileStream = stream, 
           TcpClient = client, 
           RemoteEndPoint = endPoint 
          }; 

     // read from file stream 
     int bytesRead = stream.Read(context.Buffer, 0, context.Buffer.Length); 

     // and send the data to the server 
     context.BytesSent += bytesRead; 
     client.GetStream().BeginWrite(context.Buffer, 0, bytesRead, OnWriteCompleted, context); 
    } 

    /// <summary> 
    /// File transfer have been completed 
    /// </summary> 
    public event EventHandler<CompletedEventArgs> Completed = delegate { }; 

    #region Nested type: ClientContext 

    /// <summary> 
    /// Used to keep track of all open connections 
    /// </summary> 
    private class ClientContext 
    { 
     /// <summary> 
     /// Gets or sets buffer used to send file 
     /// </summary> 
     public byte[] Buffer { get; set; } 

     /// <summary> 
     /// Gets or sets number of bytes sent. 
     /// </summary> 
     public int BytesSent { get; set; } 

     /// <summary> 
     /// Gets or sets file to send 
     /// </summary> 
     public FileStream FileStream { get; set; } 

     public IPEndPoint RemoteEndPoint { get; set; } 

     /// <summary> 
     /// Gets or sets client sending the file 
     /// </summary> 
     public TcpClient TcpClient { get; set; } 
    } 

    #endregion 
} 

internal class CompletedEventArgs : EventArgs 
{ 
    public CompletedEventArgs(IPEndPoint endPoint, string fullPath) 
    { 
     EndPoint = endPoint; 
     FullPath = fullPath; 
    } 

    public IPEndPoint EndPoint { get; private set; } 
    public string FullPath { get; private set; } 
}