gpt4 book ai didi

c# - 如何调试具有异步数据访问且没有调用堆栈的 WPF 应用程序?

转载 作者:太空宇宙 更新时间:2023-11-03 16:16:30 24 4
gpt4 key购买 nike

我有一个大型 WPF 应用程序,它使用 MVVM 设计模式和异步数据访问方法。它使用带有回调处理程序和 IAsyncResult 接口(interface)的老式异步代码...这是一个典型的例子:

function.BeginInvoke(callBackMethod, asyncState);

然后,在 View 模型中,我有以下回调处理程序:

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);
}

此问题只影响一个 View 模型,即允许用户编辑 Release 对象的 View 模型。在相关 View 中,某些填充 ComboBoxes 的集合是在首次加载时从数据库中请求的。让我们简化这一说法,即只有一个名为 Genres 的集合。数据到达 View 模型后,处理如下:

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);

在这一点上,我应该注意到这一切工作正常,并且这是唯一引用 View 模型中的 Release.Genre 属性的行。

我的特殊问题是,有时 Release.Genre 属性设置为 null,我无法弄清楚如何或从何处设置。 >> 编辑 >> 当我在属性 setter 上放置一个断点时,<< 编辑 <<调用堆栈 没有提供任何关于设置 null 值的真正线索,因为只有 [Native to Managed Transition] 行。从 Call Stack 窗口中选择 Show External Code 选项后,我可以看到基本的异步代码调用:

Call Stack

现在我可以确认我在尝试解决此问题时发现的以下事实:

  1. 引用 Release.Genre 属性的一行是将其设置为null
  2. 对 Genres.AddEmptyItemBefore(result.ReturnValue) 的调用将其设置为null...这只是将结果集合添加到Genres 添加“空”流派 后的集合。
  3. Release.Genre 属性有时会在调用 Genres.AddEmptyItemBefore(result.ReturnValue) 期间或之后设置为 null,但不会 因为它...当几次单步执行它时,执行已经(以不相关的方式)跳到我在 Release.Genre 属性 setter 上设置的断点,其中 value 输入参数为 null,但这不会每次都发生。
  4. 它通常发生在从相关 View 模型到Release View 模型时,但不是每次。
  5. 相关 View 模型没有对 Release.Genre 属性的引用。

明确地说,我并不是要任何人根据我提供的稀疏信息来调试我的问题。我也没有征求有关进行异步数据调用的建议。相反,我真的在努力寻找我还没有想到的新方法。我知道某处的某些代码(几乎可以肯定是我的代码)正在将属性设置为 null ...我的问题是如何检测此代码的位置?它似乎不在 Release View 模型中。如何在没有更多线索的情况下继续调试这个问题?

最佳答案

我通常使用平面文件、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 设置(或获取)属性中

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等。

请注意,我只是给出了构建日志记录的一般图像。请期待错误。但是,开发日志事件以满足要求是开发人员的责任。

关于c# - 如何调试具有异步数据访问且没有调用堆栈的 WPF 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15664558/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com