我有一个使用MVVM设计模式和异步数据访问方法的大型WPF应用程序。它使用带有回调处理程序的旧式异步代码和IAsyncResult
接口......这是一个典型的例子:
function.BeginInvoke(callBackMethod, asyncState);
然后,在视图模型中,我有以下回调处理程序:
private void GotData(GetDataOperationResult<Genres> result)
{
UiThreadManager.RunOnUiThread((Action)delegate
{
if (result.IsSuccess) DoSomething(result.ReturnValue);
else FeedbackManager.Add(result);
});
}
RunOnUiThread
方法基本上如下:
public object RunOnUiThread(Delegate method)
{
return Dispatcher.Invoke(DispatcherPriority.Normal, method);
}
此问题仅影响一个视图模型,即允许用户编辑Release
对象的视图模型。在相关视图中,首次加载时会从数据库中请求填充ComboBox
es的某些集合。让我们简化一下,说只有一个名为Genres
的集合。数据到达视图模型后,处理方式如下:
private void GotGenres(GetDataOperationResult<Genres> result)
{
UiThreadManager.RunOnUiThread((Action)delegate
{
if (result.IsSuccess) Genres.AddEmptyItemBefore(result.ReturnValue);
else FeedbackManager.Add(result);
});
}
当集合存在并且在UI中选择了Release
对象时,我有以下代码从集合中选择当前的Release.Genre
值:
if (!Release.Genre.IsEmpty && Genres.ContainsItemWithId(Release.Genre.Id))
Release.Genre = Genres.GetItemWithId(Release.Genre);
此时,我应该注意这一切都正常,这是 only 行,它引用了视图模型中的Release.Genre
属性。
我的特殊问题是,有时Release.Genre
属性设置为null
,我无法弄清楚如何或从哪里开始。 &GT;&GT;编辑&gt;&gt;当我在属性设置器上设置断点时,&lt;&lt;编辑&lt;&lt; Call Stack
没有提供关于设置null
值的真实线索,因为只有[Native to Managed Transition]
行。从Show External Code
窗口中选择Call Stack
选项后,我可以看到基本的异步代码调用:
现在,我可以确认在尝试解决此问题时发现的以下事实:
Release.Genre
属性的一行不将其设置为null
。null
...这只是在添加后将结果集合添加到Genres
集合中一个'空'Genre
。Release.Genre
属性有时会设置为null
,但不因为它...在某些情况下单步执行它,执行已经(以不相关的方式)跳转到我在Release.Genre
属性设置器上设置的断点,其中value
输入参数是null
,但这不每次都会发生。Release
视图模型时,通常会发生这种情况,但每次都不。Release.Genre
属性。要清楚,我并不是要求任何人从我提供的稀疏信息中调试我的问题。我也不是在寻求关于进行异步数据调用的建议。相反,我真的想找到我尚未想到的新方法。我理解某些代码(几乎可以肯定是我的代码)将属性设置为null
...我的问题是如何检测此代码的位置?它似乎不在Release
视图模型中。如何在没有更多线索的情况下继续调试此问题?
答案 0 :(得分:0)
我通常使用平面文件,XML或数据库日志记录进行调试。我为记录目的创建了这些Log类,以便我可以从我开发的每个应用程序中调用它。
对于数据库日志记录,您可以这样做:
void WriteLog(string log){
// Your database insert here
}
也许您需要日期时间和其他支持信息,但这取决于开发人员。对于简单的平面文件记录是:
void WriteLog(string log){
using(TextWriter tx = new StreamWriter("./Log/" + DateTime.Now.ToString() + ".txt", false)){
tx.WriteLine(log);
}
}
您可以通过以下两种方式使用应用程序中的日志记录:
1:方法调用
WriteLog((Release.Genre == null).ToString());
if (!Release.Genre.IsEmpty && Genres.ContainsItemWithId(Release.Genre.Id))
Release.Genre = Genres.GetItemWithId(Release.Genre);
2:将其添加到您的Release.Genre set(或get)属性
中public class Release{
private Genre _genre=null;
public Genre Genre{
get{
WriteLog((_genre == null).ToString());
return _genre;
}
set{
WriteLog((_genre == null).ToString());
_genre = value;
}
}
}
有了这个,您可以尝试获取呼叫顺序,无论是在呼叫期间,呼叫期间是否在其他地方设置了Release.Genre。
请注意我只是给出了建筑物测井的一般图像。请指望错误。但是,开发人员有责任开发Logging acitivities以满足要求。