如何状态信息传递给GUI松散耦合的应用 [英] How to pass status information to the GUI in a loosely coupled application

查看:166
本文介绍了如何状态信息传递给GUI松散耦合的应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经作出了在使用依赖注入来松散耦合新的应用程序第一次尝试。我的问题是如何传递状态信息返回给用户。在旧天塞进了GUI的所有代码是,如果非常混乱和难以维护很容易。类的安排是这样的(请不要检查我的UML技能 - 他们是不存在的):

I have made my first attempt at using dependency injection to loosely couple a new application. My problem is how to pass status information back to the user. In the old days with all the code crammed into the GUI it was pretty easy if very messy and unmaintainable. The arrangement of classes is something like this (please do not check my UML skills - they are non existent):

如果我们把右手边。该AirportsInformationRepository只是存储数据,并提供给控制器当记者问。一开始它会用坚持类来获得匹配的文件从用户的硬盘驱动器给定的过滤器的信息。它使用反编译器从文件中提取信息。所有这一切工作正常,信息本身获取到图形用户界面,因为它应该。

If we take the right hand side. The AirportsInformationRepository just stores data and makes it available to the Controller when asked. At the start it gets the information using the Persist class to get files matching a given filter from the users hard drive. It uses the decompiler to extract information from a file. All this works fine and the information itself gets to the GUI as it should.

我的问题是,在并行,如何告诉发生了什么用户。这可以发生在反编译,例如,如果它获得的文件不能被反编译或也许不包含数据。如果配置文件是在说谎它可以发生在坚持阶级和一些文件夹不存在。除非有一个致命的错误这类问题应该不能停止的过程。

My problem is, in parallel, how to tell the user what is happening. This can occur in the decompiler, for example, if the file it gets cannot be decompiled or perhaps contains no data. It can occur in the Persist class if the config file is telling lies and some folder does not exist. Such issues should not stop the process unless there is a fatal error.

如果有一个致命错误,那么就需要返回到用户的一次,整个过程应该停止。否则,警告,可以通过程序来收集不知何故,然后当扫描完成显示。

If there is a fatal error then it needs to get back to the user at once and the overall process should stop. Otherwise warnings can be collected through the process somehow and then displayed when the scan is completed.

我所熟悉的日志和应用程序确实有被监视的应用程序记录器未处理异常等故障。此写入磁盘,我用这个最喜欢的会来处理错误。我不想用这个状态报告给用户,因为是如果没有找到一个文件或用户输入的配置文件的路径无效诚实没有什么是错的应用程序。

I am familiar with logging and the application does have a logger that is monitoring the application for unhandled exceptions and other failures. This writes to disk and I use this like most would to deal with bugs. I don't want to use this for status reporting to the user since to be honest nothing is wrong with the app if a file is not found or the user entered an invalid path to the config file.

我已经考虑:


  • 积累了日志中的每个类,并通过它传回给消费者时,该过程完成(或失败)。我发现这真的很乱

  • 使用事件,但如果消费者订阅和事件向上传递链以同样的方式作为日志,然后我看不出要好得多。我猜测另一种方法是有GUI直接认购,但它不应该知道的反编译....

  • 任何一个家庭卷起记录器是一个静态类或程序被实例化的.cs

  • 某种消息的框架 - 这点我承认,我不清楚,但我认为是相当类似于中央事件处理由此GUI可以订阅它,而不必知道什么对其他类。

  • accumulating a log in each class and passing it back to the consumer when the process completes (or fails). I am finding that really messy
  • using events but if the consumer is subscribing and the events are passing up the chain in the same way as the log then I don't see that is much better. I guess an alternative is to have the GUI subscribe directly but it should not know anything about the decompiler....
  • A home rolled logger that is either a static class or is instantiated in program.cs
  • Some sort of messaging framework - which I admit I am not clear about but I think is rather similar to a central event handler whereby the GUI could subscribe to it without having to know anything about the other classes.

总结一下。什么是积累一切如常的状态信息,并给它的图形用户界面在扫描结束后,在同一时间能够停止的致命问题的最佳途径。

So to summarise. What is the best way to accumulate 'business as usual' status information and give it to the GUI at the end of a scan, at the same time being able to stop on a fatal issue.

在此先感谢您阅读本。道歉后的长度。

Thanks in advance for reading this. Apologies for the length of the post.

修改
我应该说,应用程序是使用.NET 3.5。我会改变这得到一个完美的解决方案,但....

EDIT I should have said that the app is using NET 3.5. I would change this to get an elegant solution but....

推荐答案

在处理加工的典型的流 ,甚至可能是多线程/并行处理流程的最佳方法采取的是邮筒/消息泵。通过exchaging消息,可以很容易地配合您的应用程序的多个层,这包括报告错误,通知等命令的下一个链条。我的意思不是Windows消息,我的意思是这样的:

When you deal with a typical "flow" of processing, possibly even multithreaded/concurrent processing flow the best approach to take is "mailslots"/message pumps. By exchaging messages you can easily coordinate multiple layers of your application and that includes reporting errors, notifying the next chain of command etc.. I do not mean Windows messages, I mean something like:

public abstract class Message
{
   public abstract void Process();
} 



然后:

Then:

public class MessageQueue
{
   private Queue m_Queue;
   public void Post(Message msg) {....}
   public void Process() {.....}
}

然后你在你的应用程序的每个线程/处理层分配的MessageQueue,并通过像这样的消息:

Then you allocate a MessageQueue on every thread/processing tier of your app and pass messages like so:

    GUIMessageQueue.Post(
           new ErrorMessage("Internal async file reader ran out of buffer"));  

在GUI线程把读取GUI队列,并调用它的过程()一个计时器。
现在,您可以创建很多消息来源的工作项目来执行的线程/逻辑层之间非常容易地协调各种任务。此外,消息可能包含在其涉及的datapieces引用:

On GUI thread put a timer that read GUI queue and calls it's Process(). Now you can create many Message-derived work items to execute various tasks that very easily orchestrate between threads/logical tiers. Also, messages may contain references for datapieces that they relate to:

公共AirplaneLandedMessage:消息
{
公共飞机飞机......
}

public AirplaneLandedMessage: Message { public Airplane Plane ...... }

下面是我在大规模并行链处理系统中使用一些实际的代码:

Here is some real code that I use in massively parallel chain-processing system:

/// <summary>
/// Defines a base for items executable by WorkQueue
/// </summary>
public interface IWorkItem<TContext> where TContext : class
{
  /// <summary>
  /// Invoked on an item to perform actual work. 
  /// For example: repaint grid from changed data source, refresh file, send email etc... 
  /// </summary>
  void PerformWork(TContext context);

  /// <summary>
  /// Invoked after successfull work execution - when no exception happened
  /// </summary>
  void WorkSucceeded();

  /// <summary>
  /// Invoked when either work execution or work success method threw an exception and did not succeed
  /// </summary>
  /// <param name="workPerformed">When true indicates that PerformWork() worked without exception but exception happened later</param>
  void WorkFailed(bool workPerformed, Exception error);

}


/// <summary>
/// Defines contract for work queue that work items can be posted to
/// </summary>
public interface IWorkQueue<TContext> where TContext : class
{
  /// <summary>
  /// Posts work item into the queue in natural queue order (at the end of the queue)
  /// </summary>
  void PostItem(IWorkItem<TContext> work);

  long ProcessedSuccessCount{get;}
  long ProcessedFailureCount{get;}

  TContext Context { get; }
}

这篇关于如何状态信息传递给GUI松散耦合的应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆