0

我正在尝试编写一个将文件从服务器传输到客户端的软件......这就是我的软件的工作方式......在客户端它获取一个 IP 和一个端口,然后从 Client 类生成一个新对象到一个新线程并将 ip 和端口传递给构造函数,客户端处理连接并将文件传输到 byte[] 变量..现在我想用 saveFileDialog 提示用户保存文件......但是我无权访问作为我的表单的父类。所以我不能做像 savefiledialog.ShowDialog() 这样的事情......这个问题的解决方案是什么?

4

2 回答 2

2

使用事件

http://msdn.microsoft.com/en-us/library/awbftdfh.aspx

使用后台工作者而不是您自己的线程:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.100).aspx

于 2012-09-13T09:40:53.197 回答
2

@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 FileDownloadCompletedfor instance。

还要注意+=语法。您不会事件分配给函数,而是告诉事件在发生某些事情时调用该函数。如果需要,您甚至可以在同一个事件中使用两个函数。

于 2012-09-13T12:34:14.470 回答