目前,我有类似的内容:
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();
}
哪个工作正常 - 这个例子来自样本。但是,在最近重新访问后,我有一个问题。在这种特殊情况下,因为OnResponse()函数不更新UI,所以在这里似乎没有用处。我删除了它(以及它的所有调用),它仍然像以前一样工作。我错过了什么吗?
在阅读了有关表单的多线程的更多信息后,我开始明白这个机制(在上面的代码中演示)是为了确保UI响应。
因此,如果我们需要说更新UI元素(例如文本框,标签等),我们将按如下方式实现OnResponse:
delegate void StringDelegate(string dummy);
void OnResponse(string dummy)
{
if(!InvokeRequired)
{
button1.Text = dummy;
}
else
Invoke(new StringDelegate(OnResponse),new object[] {enabled});
}
如果此功能实现为:
delegate void StringDelegate(string dummy);
void OnResponse(string dummy)
{
if(InvokeRequired)
{
Invoke(new StringDelegate(OnResponse),new object[] {dummy});
return;
}
}
有什么用呢?是绝对必要的吗?
还有一个问题:ftp对象是否在自己的线程上运行?
答案 0 :(得分:1)
FTP对象肯定在自己的线程上运行。我怎么知道?这一行:
m_ftp.BeginConnect(user.Text, password.Text);
这是一种异步方法。一旦调用它,FTP组件将使用.NET线程池中的线程来完成所有工作。这个专用线程是用于“引发”事件的线程。最终,“引发事件”只是对添加到事件调用列表中的所有代理的一个或多个方法调用;这是由Begin方法调出的专用线程,它调用这些方法。该线程与运行UI的线程不是同一个线程,因此需要调用Invoke。
如果您希望FTP组件使用UI线程,则使用Connect方法而不是BeginConnect方法。这意味着您的事件也不会工作,您的UI也不会响应交互 - 这完全是预期的,因为一个线程一次只能做一件事:它要么为UI提供服务,要么执行FTP代码。这就是你需要第二个线程的原因。
有意义吗?
-Oisin