0

到目前为止,我在 Windows 窗体中使用 FTP 对象。FTP 对象在单独的线程中运行,因此为了确保我的应用程序不会冻结,我使用以下代码:

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

我不完全清楚字符串委托是什么,但这有效。

但是,我现在正在重构并希望将 ftp 隐藏到一个类中。我的问题是如何确保主线程不会冻结?所有关于在类中引发事件的在线参考资料都是有意义的,但我还没有找到一个应用程序是多线程的示例。我最关心的是 InvokeRequired。

在上面的代码中,这是一个表单。如果我将 ftp 对象隐藏在一个类中,如下所示:

abstract class MyClass
{
    //data members
    private FTP _ftp;

    //other data members, methods, and properties etc
}

"This" 成为 MyClass 的一个对象。我不确定是否在类上实现了 InvokeRequired 属性(也许我应该让它实现一个具有该属性的特殊接口?)。或者也许我遗漏了一些东西,我不应该在类中使用多线程对象?

4

2 回答 2

1

您需要在 UI 线程上创建的 Control 或从 Control 派生的东西(不一定是 Form)。您的 MyClass 可能不应该直接更新 UI,因此在这里并不真正相关 - MyClass 可能会引发事件或调用回调。

当您想根据来自 FTP 库的事件更改表单上的某些内容时,UI 变得很重要。为此,您需要在 UI 线程上创建的 Control 或从 Control 派生的任何内容(同样,不必是 Form)。使用该控件检查 InvokeRequired,如果为真,则调用 Invoke。原始版本使用自定义委托(可能来自 FTP 示例,因为它看起来对我来说非常熟悉),但您可以使用任何您想要的委托。

网络上有很多使用 Control.Invoke 的示例,因此您应该能够相当容易地实现它。

于 2009-05-22T21:12:23.127 回答
0

最可能的设计方法是让“MyClass”的调用者根据需要调用或不调用。我会设计您的课程以在响应发生时触发事件。

请记住,只有与 Windows UI 交互的代码需要 Invoke-d 到主线程上。OnResponse 中的任何其他处理都可以在后台线程中完成,没有问题。

如果您的“MyClass”不是窗体或控件之类的 Windows 对象,那么您就没有您所说的 InvokeRequired。但它不需要 InvokeRequired。如果代表 UI 对象的其他类确实需要对 FTP 对象做出响应,那么该 UI 对象可以执行 InvokeRequired 测试。

我希望这很清楚!


编辑:添加信息

OnReceived 处理程序肯定会在您的 FTP 类中。所以我在想这样的事情:

公共类 MyFTPClass { 公共事件 EventHandler DataReceived; // UI 表单可以订阅这个事件

 private void OnReceived()
 {
   //so the FTP has returned data
   // Do stuff here that can be on the background thread like saving
   // the file in an appropriate place, or whatever.


   // now trigger the DataReceived event.  Anyone who cares about data being received
   // can subscribe to this and do whatever is appropriate.
   if (DataReceived) DataReceived(this, EventArgs.Empty); 

}

这是一个粗略的轮廓。但基本思想是你在后台线程中做你可以做的事情。然后您可以通过事件通知 UI。

于 2009-05-22T18:41:27.343 回答