2009-05-25 8 views
1

Derzeit habe ich so etwas wie:OpenNetCF FTP Klasse Multithreading Frage

public partial class Form1 : Form 
{ 
delegate void StringDelegate(string value); 

private FTP m_ftp; 

public Form1() 
{ 
InitializeComponent(); 
} 

private void connect_Click(object sender, EventArgs e) 
{ 
OnResponse("Connecting"); 
m_ftp = new FTP(server.Text); 
m_ftp.ResponseReceived += new FTPResponseHandler(m_ftp_ResponseReceived); 
m_ftp.Connected += new FTPConnectedHandler(m_ftp_Connected); 
m_ftp.BeginConnect(user.Text, password.Text); 
} 

void m_ftp_Connected(FTP source) 
{ 
// when this happens we're ready to send command 
OnResponse("Connected."); 
} 

void m_ftp_ResponseReceived(FTP source, FTPResponse Response) 
{ 
OnResponse(Response.Text); 
} 

private void OnResponse(string response) 
{ 
if (this.InvokeRequired) 
{ 
this.Invoke(new StringDelegate(OnResponse), new object[] { response }); 
return; 
} 

} 

private void getFileList_Click(object sender, EventArgs e) 
{ 
FTPFiles files = m_ftp.EnumFiles(); 

fileList.Items.Clear(); 

foreach (FTPFile file in files) 
{ 
fileList.Items.Add(new ListViewItem(new string[] { file.Name, file.Size.ToString() })); 
} 

tabs.SelectedIndex = 1; 
} 

private void upload_Click(object sender, EventArgs e) 
{ 
FileStream stream = File.OpenRead("\\My Documents\\My Pictures\\Waterfall.jpg"); 
m_ftp.SendFile(stream, "waterfall.jpg"); 
stream.Close(); 
} 

die gut arbeitet - dieses Beispiel aus den Proben genommen wurde. Nach einem kürzlichen erneuten Besuch habe ich eine Frage. In diesem speziellen Fall, da die OnResponse() - Funktion die Benutzeroberfläche nicht aktualisiert, scheint sie hier keinen Zweck zu erfüllen. Ich entfernte es (sowie alle Anrufe dazu) und es funktioniert immer noch wie zuvor. Fehle ich etwas?

Nachdem ich mehr über Multi Threading mit Formularen gelesen habe, habe ich verstanden, dass dieser Mechanismus (im obigen Code demonstriert) vorhanden ist, um sicherzustellen, dass die Benutzeroberfläche reaktionsfähig ist.

So im Falle, wenn wir sagen müssen, aktualisieren Sie ein UI-Element (wie Textbox, Label usw.) wir OnResponse umgesetzt würden wie folgt:

delegate void StringDelegate(string dummy); 
void OnResponse(string dummy) 
{ 
    if(!InvokeRequired) 
    { 
     button1.Text = dummy; 
    } 
    else 
     Invoke(new StringDelegate(OnResponse),new object[] {enabled}); 
} 

Ist diese Funktion wie implementiert:

delegate void StringDelegate(string dummy); 
    void OnResponse(string dummy) 
    { 
     if(InvokeRequired) 
     {    
      Invoke(new StringDelegate(OnResponse),new object[] {dummy}); 
      return; 
     } 
    } 

Was nützt es überhaupt? Ist es unbedingt notwendig?

Und eine andere Frage: Ist FTP-Objekt auf einem eigenen Thread hier ausgeführt?

Antwort

1

Das FTP-Objekt läuft definitiv auf einem eigenen Thread. Wie soll ich wissen? Diese Zeile:

m_ftp.BeginConnect(user.Text, password.Text); 

Dies ist eine asynchrone Methode. Sobald Sie dies aufrufen, verwendet die FTP-Komponente einen Thread aus dem .NET-Threadpool, um die gesamte Arbeit auszuführen. Dieser dedizierte Thread ist derjenige, mit dem die Ereignisse "ausgelöst" werden. Letztendlich ist ein "ausgelöstes Ereignis" nur ein oder mehrere Methodenaufrufe an alle Delegaten, die der Ereignisaufrufliste hinzugefügt wurden. Es ist dieser dedizierte Thread, der von der Begin-Methode aufgerufen wird und diese Methoden aufruft. Dieser Thread ist nicht derselbe Thread wie der Thread, der die Benutzeroberfläche ausführt. Daher müssen Aufrufe aufgerufen werden.

Wenn die FTP-Komponente den UI-Thread verwenden soll, verwenden Sie die Connect-Methode anstelle der BeginConnect-Methode. Das bedeutet, dass Ihre Ereignisse nicht funktionieren und Ihre Benutzeroberfläche auch nicht auf Interaktionen reagiert. Dies wird vollständig erwartet, da ein Thread nur eine Aufgabe gleichzeitig ausführen kann: Entweder bedient er die Benutzeroberfläche oder führt den FTP-Code aus. Deshalb brauchen Sie einen zweiten Thread.

Sinn machen?

-Oisin

+0

Vielen Dank! Sorta tut es. Der aktuelle Code kann die Benutzeroberfläche in m_ftp_ResponseReceived() aktualisieren ... Deshalb bin ich verwirrt. Mein Verständnis war, dass FTP-Objekt in seinem eigenen Thread ausgeführt wurde, aber dann sollte ich nicht in der Lage sein, UI in m_ftp_ResponseReceived() zu aktualisieren, wenn ich Invokes verwende. Was gibt? Ich möchte weiterhin das BeginConnect() verwenden, da ich möchte, dass die Benutzeroberfläche reagiert. – sarsnake

+0

Bitte beachten Sie auch, dass OpenNetCF keine Connect-Methode in der FTP-Klasse hat, nur BeginConnect() – sarsnake

+0

Ich habe es gerade mehr getestet, und es sieht so aus, als ob ich die Benutzeroberfläche von m_ftp_ResponseReceived() aktualisieren könnte. aber nicht möglich, es aus m_ftp_Connected() zu tun. Ziemlich interessante Beobachtung. m_ftp_Connected muss im UI-Thread ausgeführt werden. – sarsnake