从分层应用程序中的后台线程调用
Invoke from background thread in layered application
Windows 形成应用程序,在单独的线程中进行繁重的处理。在处理的某个地方,我需要从用户那里得到一些反馈(比如询问一些关于视觉输出到另一台设备的问题)。如果我要在 UI 层中执行此操作,我会非常乐意使用控件的 Invoke
来执行此操作。处理在业务层完成。问了下业务层的大家,没有人知道Control
、Invoke
、MainForm
等关键字,怎么通知Main form获取输入呢? (事件?还是我漏掉了一些简单的东西?)
您需要让您的请求从业务层向上传播,然后从您的 UI 中的表示层调用它。
正如您在评论中所建议的那样,一种方法是使用从业务层触发并由表示层处理的事件,但这取决于您是否要构建您的应用程序使用事件在层之间进行通信。
我个人的偏好是让各层直接相互通信,因此在这种情况下,我会让业务层与请求输入的表示层通信,然后由表示层整理请求通过 Invoke
.
到视图 (UI) 本身
一种方法是在您的业务层中创建一个 event,您从中连接到您的 control/form 代码。当您的 control/form 收到事件时,编组回 UI 线程调用 Invoke/BeginInvoke 以相应地更新您的控件。
例如,在您的型号代码中:
public class ModelFoo
{
public event EventHandler SomethingInterestingHappened;
...
当您调用(或广播)事件时,通常的做法是通过 "On" 方法 (make the call thread-safe - see also this):
private void
OnSomethingInterestingHappened
()
{
var SomethingInterestingHappenedCopy = SomethingInterestingHappened;
if (SomethingInterestingHappenedCopy != null)
{
// TODO add your event data in the second args here
SomethingInterestingHappenedCopy (this, EventArgs.Empty);
}
}
然后从您的 UI 主题订阅它,例如:
ModelFoo.SomethingInterestingHappened += SomethingInterestingHappenedHandler;
其中:
private void SomethingInterestingHappenedHandler(object sender, EventArgs e)
{
// You can call if(this.InvokeRequired) here, since
// you might already be on the UI thread.
// However from other threads call Invoke/BeginInvoke if wanting
// to process synchronously/asynchronously depending on what you need and
// you need to update a control object.
Invoke(new MethodInvoker(delegate
{...
我发现事件非常有用,因为它 feels like 您可以很好地将 UI 与模型分离。事件也可以在接口上定义,因此 UI 代码可以与抽象的东西对话,这意味着您可以在需要时更改基础类型(例如用于测试)。
Windows 形成应用程序,在单独的线程中进行繁重的处理。在处理的某个地方,我需要从用户那里得到一些反馈(比如询问一些关于视觉输出到另一台设备的问题)。如果我要在 UI 层中执行此操作,我会非常乐意使用控件的 Invoke
来执行此操作。处理在业务层完成。问了下业务层的大家,没有人知道Control
、Invoke
、MainForm
等关键字,怎么通知Main form获取输入呢? (事件?还是我漏掉了一些简单的东西?)
您需要让您的请求从业务层向上传播,然后从您的 UI 中的表示层调用它。
正如您在评论中所建议的那样,一种方法是使用从业务层触发并由表示层处理的事件,但这取决于您是否要构建您的应用程序使用事件在层之间进行通信。
我个人的偏好是让各层直接相互通信,因此在这种情况下,我会让业务层与请求输入的表示层通信,然后由表示层整理请求通过 Invoke
.
一种方法是在您的业务层中创建一个 event,您从中连接到您的 control/form 代码。当您的 control/form 收到事件时,编组回 UI 线程调用 Invoke/BeginInvoke 以相应地更新您的控件。
例如,在您的型号代码中:
public class ModelFoo
{
public event EventHandler SomethingInterestingHappened;
...
当您调用(或广播)事件时,通常的做法是通过 "On" 方法 (make the call thread-safe - see also this):
private void
OnSomethingInterestingHappened
()
{
var SomethingInterestingHappenedCopy = SomethingInterestingHappened;
if (SomethingInterestingHappenedCopy != null)
{
// TODO add your event data in the second args here
SomethingInterestingHappenedCopy (this, EventArgs.Empty);
}
}
然后从您的 UI 主题订阅它,例如:
ModelFoo.SomethingInterestingHappened += SomethingInterestingHappenedHandler;
其中:
private void SomethingInterestingHappenedHandler(object sender, EventArgs e)
{
// You can call if(this.InvokeRequired) here, since
// you might already be on the UI thread.
// However from other threads call Invoke/BeginInvoke if wanting
// to process synchronously/asynchronously depending on what you need and
// you need to update a control object.
Invoke(new MethodInvoker(delegate
{...
我发现事件非常有用,因为它 feels like 您可以很好地将 UI 与模型分离。事件也可以在接口上定义,因此 UI 代码可以与抽象的东西对话,这意味着您可以在需要时更改基础类型(例如用于测试)。