到目前为止,我在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
}
“这个”成为MyClass的一个对象。我不确定是否在类上实现了InvokeRequired属性(也许我应该让它实现一个具有该属性的特殊接口?)。或许我错过了一些东西,我不应该在类中使用多线程对象?
答案 0 :(得分:1)
您需要在UI线程上创建的Control或从Control派生的内容(不必是Form)。你的MyClass可能不应该直接更新UI,所以它在这里并不真正相关 - MyClass可能会引发一个事件或调用一个回调。
如果要根据来自FTP库的事件更改窗体上的内容,请在UI处重要。为此,您需要在UI线程上创建的Control或从Control派生的任何内容(同样,不必是Form)。使用该控件检查InvokeRequired,如果为true,则调用Invoke。原始使用自定义委托(可能来自FTP示例,因为它看起来我非常熟悉),但您可以使用任何您想要的委托。
网上有很多使用Control.Invoke的例子,所以你应该可以很容易地实现它。
答案 1 :(得分:0)
设计此方法的最可能方法是让“MyClass”调用者根据需要调用或不调用。我会设计你的类来在响应发生时触发一个事件。
请记住,它只是与需要在主线程上调用的Windows UI交互的代码。 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。