2

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

この問題は、ユーザーがオブジェクトを編集できるようにする 1 つのビュー モデルにのみ影響しReleaseます。関連するビューでは、最初に読み込まれるときに、データベースからデータを取り込む特定のコレクションComboBoxが要求されます。と呼ばれるコレクションが 1 つだけあると言って、これを単純化しましょうGenres。データがビュー モデルに到着すると、次のように処理されます。

private void GotGenres(GetDataOperationResult<Genres> result)
{
    UiThreadManager.RunOnUiThread((Action)delegate
    {
        if (result.IsSuccess) Genres.AddEmptyItemBefore(result.ReturnValue);
        else FeedbackManager.Add(result);
    });
}

コレクションが存在Releaseし、UI でオブジェクトが選択されている場合、次のコードRelease.Genreでコレクションから現在の値を選択します。

if (!Release.Genre.IsEmpty && Genres.ContainsItemWithId(Release.Genre.Id)) 
    Release.Genre = Genres.GetItemWithId(Release.Genre);

この時点で、これはすべて正常に機能し、これがビュー モデルからプロパティを参照する唯一の行であることに注意してください。Release.Genre

私の特定の問題は、Release.Genreプロパティが設定されていることがあり、nullどのように、またはどこから解決できないことです。>> 編集 >> プロパティ セッターにブレーク ポイントを配置すると、<< 編集 << は、行しかないためCall Stack、値を設定しているものに関する実際の手がかりを提供しません。ウィンドウからオプションを選択すると、基本的な非同期コード呼び出しが表示されます。null[Native to Managed Transition]Show External CodeCall Stack

コール スタック

この問題を解決しようとしているときに発見した次の事実を確認できます。

  1. Release.Genreプロパティを参照する1行は、それをに設定していませんnull
  2. Genres.AddEmptyItemBefore(result.ReturnValue) への呼び出しはそれを設定していませんnull...これはGenres、 'empty' を追加した後に結果コレクションをコレクションに追加するだけGenreです。
  3. Release.Genreプロパティは、Genres.AddEmptyItemBefore(result.ReturnValue) の呼び出し中または呼び出し後に設定されることがありますが、nullそれが原因ではありません... いくつかの場合にステップスルーすると、実行が (無関係な方法で) ブレークにジャンプしました入力パラメーターがであるRelease.Genreプロパティ セッターに設定したポイントですが、これは毎回発生しません。valuenull
  4. 通常、関連するビュー モデルからビュー モデルに移動するときに発生しReleaseますが、毎回ではありません。
  5. 関連するビュー モデルには、Release.Genreプロパティへの参照がありません。

明確にするために、私が提供したまばらな情報から私の問題をデバッグするように誰かに頼んでいるわけではありません。また、非同期データ呼び出しについてアドバイスを求めているわけでもありません。代わりに、私はまだ考えていない新しい進行方法を見つけようとしています。一部のコード (ほぼ確実に私のコード) のどこかでプロパティが設定されていることを理解していますnull...私の質問は、このコードがどこにあるかをどのように検出できますか? Releaseビューモデルにはないようです。手がかりがないまま、この問題をデバッグし続けるにはどうすればよいですか?

4

1 に答える 1

0

私は通常、デバッグ目的でフラット ファイル、XML、またはデータベース ロギングを使用します。開発するすべてのアプリケーションから呼び出すことができるように、ロギング目的でこれらの Log クラスを作成しました。

データベース ロギングの場合は、次のように簡単に実行できます。

void WriteLog(string log){
  // Your database insert here
}

datetime やその他のサポート情報が必要な場合もありますが、それは開発者次第です。単純なフラット ファイル ロギングの場合は次のとおりです。

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 アクティビティを開発するのは開発者の責任です。

于 2013-03-27T17:33:50.623 に答える