我正在尝试编写一个将文件从服务器传输到客户端的软件......这就是我的软件的工作方式......在客户端它获取一个 IP 和一个端口,然后从 Client 类生成一个新对象到一个新线程并将 ip 和端口传递给构造函数,客户端处理连接并将文件传输到 byte[] 变量..现在我想用 saveFileDialog 提示用户保存文件......但是我无权访问作为我的表单的父类。所以我不能做像 savefiledialog.ShowDialog() 这样的事情......这个问题的解决方案是什么?
2 回答
使用事件
http://msdn.microsoft.com/en-us/library/awbftdfh.aspx
使用后台工作者而不是您自己的线程:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.100).aspx
@syned 建议的事件是一个很好的解决方案。它是一种观察者,但在此示例中,您需要与可观察类(客户端)进行交互。
您可以在您的客户端类中声明一个事件,因此当要接收文件时可以使用此事件。一种正常的方法是有一个特殊的“上下文类”,你可以用你需要的值来填充它。
public class Client {
public event EventHandler<ReceivedFileEventArgs> ReceivedFile;
private ReceivedFileEventArgs onReceivedFile() {
EventHandler<ReceivedFileEventArgs> handler = ReceivedFile;
ReceivedFileEventArgs args = new ReceivedFileEventArgs();
if (handler != null) { handler(this, args); }
return args;
}
private void receiveFileCode() {
// this is where you download the file
ReceivedFileEventArgs args = onReceivedFile();
if (args.Cancel) { return; }
string filename = args.FileName;
// write to filename
}
}
public class ReceivedFileEventArgs {
public string FileName { get; set; }
public bool Cancel { get; set; }
}
现在,在您的 GUI 类中,您可以“监听”此事件,并将文件名设置为您想要的。
public class MyForm : Form {
public MyForm() { Initialize(); }
protected void buttonClick(object sender, EventArgs e) {
// Suppose we initialize a client on a click of a button
Client client = new Client();
// note: don't use () on the function here
client.ReceivedFile += onReceivedFile;
client.Connect();
}
private void onReceivedFile(object sender, ReceivedFileEventArgs args) {
if (InvokeRequired) {
// we need to make sure we are on the GUI thread
Invoke(new Action<object, args>(onReceivedFile), sender, args);
return;
}
// we are in the GUI thread, so we can show the SaveFileDialog
using (SaveFileDialog dialog = new SaveFileDialog()) {
args.FileName = dialog.FileName;
}
}
}
那么,什么是事件?简单来说,它是一个函数指针(但请阅读它以获取更多详细信息)。因此,您告诉您的客户端类在发生某些事情时调用该函数,例如当要接收文件时。在使用 Windows 窗体时,您几乎一直使用事件,例如当您将按钮单击分配给代码隐藏文件中的函数时。
现在,使用这种模式,您可以拥有更多事件,例如 a FileDownloadCompleted
for instance。
还要注意+=
语法。您不会将事件分配给函数,而是告诉事件在发生某些事情时调用该函数。如果需要,您甚至可以在同一个事件中使用两个函数。