【发布时间】:2013-01-26 02:00:31
【问题描述】:
我有一个类,旨在为在整个应用程序中多次使用的某些特定文件提供对某些元数据的快速访问。不幸的是,一些元数据只能通过非常长时间运行的方法调用来提取。
我有另一个类为长时间运行的方法提供异步包装器(可能是 5 分钟或更长时间,具体取决于文件的大小),但我正在尝试弄清楚如何调用此异步方法以及是否调用将其放入构造函数中是合适的,或者对于这种情况有更好的设计模式。
这里有一些伪代码来尝试说明我的问题:
public class MetaData
{
public string Data1 { get; private set; }
public string Data2 { get; private set; }
public MetaData(String filepath)
{
var extractor = new ExtractMetaData(filepath); //create instance of class that fetches the metadata
this.Data1 = extractor.GetData1(); // short running method
extractor.Data2Received += Data2Received;
extractor.GetData2Async(); // long running method, called with via async method
}
private void Data2Received(object sender, MetaDataEventArgs args)
{
this.Data2 = args.Data; // finally set Data2 property
}
}
class ExtractMetaData
{
public event Data2ReceivedEventHandler Data2Received;
public ExtractMetaData (string filePath) { }
public String GetData1(); // very fast method to get Data1
public void GetData2Async(); // very slow method to get Data2
}
我想弄清楚是否有更好的方法来实现这一点?
现在使用我的代码,几乎不需要等待构造 MetaData,但是如果有人在 GetData2Async() 方法返回并触发 Data2Received 事件之前尝试访问 MetaData.Data2 属性,他们将收到null 回复。但是如果他们在返回后调用 if ,它将包含正确的信息。由于确实没有办法通知用户此方法已完成,我担心这会变成糟糕的用户体验,因为他们不必等待构造函数,而是必须等待所有属性设置。
【问题讨论】:
-
我认为这取决于上下文,如您提供的 API 类型,但我可能会以异步回调形式或阻塞标准调用的形式提供调用。在这种情况下,我认为包装器不会真正获得任何好处,除非您能够返回部分答案,否则我认为您无法真正设计出解决方法。只是我的意见,但我会将选择权留给调用者,并集中精力优化该例程。
-
@Tim 包装器实际上是我为其他目的编写的独立库的一部分,它恰好提供异步功能以避免阻塞。这只是 10 或 15 秒的问题,我可能会选择阻塞方法,但是当我意识到可能是 5 分钟时,我开始考虑另一种方法(在构造函数中调用异步方法)。
-
抱歉,我想我的意思是我不认为有任何技巧可以应用于包装器以在客户清晰度或性能方面获得任何东西(除非部分答案有一些用处)。包装器本身仍然允许您将“啊,这个方法很慢,所以我需要封装它”逻辑与解析逻辑分开,所以我相信它是值得的。
-
@Tim 至于优化例程,那是不可能的......实际的长时间运行方法是我无法控制的外部库。我的选择真的只有,没有长期运行方法获得的数据,或者长期执行时间。我选择了后者,因为额外的数据对我的 API 的某些部分非常有用。
标签: c# .net design-patterns .net-3.5