【问题标题】:Invoke from background thread in layered application从分层应用程序中的后台线程调用
【发布时间】:2015-01-23 14:35:42
【问题描述】:

Windows 窗体应用程序,在单独的线程中进行繁重的处理。在处理过程的某个地方,我需要从用户那里获得一些反馈(比如询问一些关于视觉输出到另一台设备的问题)。如果我要在 UI 层执行此操作,我会非常乐意使用控件的 Invoke 并执行此操作。处理在业务层完成。我问了业务层的每个人,没有人知道ControlInvokeMainForm 等关键字。我如何通知主窗体并获取输入? (事件?还是我错过了一些简单的东西?)

【问题讨论】:

  • 您应该将其实现为事件或服务,基本上通过调用服务或触发事件来询问“是否有人对此过程有任何输入”。您应该考虑如果不存在服务或事件处理程序会发生什么,可以,只是没有输入,还是错误?这个问题需要向用户询问,这需要发生在 UI 线程上,这不是您现在正在处理的层的问题。

标签: c# multithreading winforms invoke


【解决方案1】:

您需要让您的请求从业务层向上传播,然后从 UI 中的表示层调用它。

正如您在评论中所建议的那样,一种方法是使用从业务层触发并由表示层处理的事件,但这取决于您是否要将应用程序架构成使用事件在层之间进行通信。

我个人的偏好是让层之间直接通信,所以在这种情况下,我会让业务层与请求输入的表示层通信,然后表示层将请求编组到通过Invoke 查看(UI)本身。

【讨论】:

  • 这是我结束的事件吗?
  • 对不起,你能重述一遍吗?
  • 这是否意味着我需要引发事件才能到达 UI 然后调用?
  • 这取决于您如何构建应用程序以在层之间进行通信。
【解决方案2】:

一种方法是在您的业务层中创建一个event,您可以从该层从您的控件/表单代码中连接到该event。当您的控件/表单接收到事件时,编组回调用 Invoke/BeginInvoke 的 UI 线程,以便相应地更新您的控件。

例如在您的模型代码中:

public class ModelFoo
{
    public event EventHandler SomethingInterestingHappened;
...

当您调用(或广播)该事件时,通常的做法是通过“开启”方法(@​​987654322@ - 另见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 代码可以与抽象的东西对话,这意味着您可以在需要时更改底层类型(例如用于测试)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多