2017-07-28 9 views
0

をしません待つ凍結しない:のWPF MVVM私は私のUIを次の手順を実行した場合、タスクの遅延が

XAMLバインディング:

<Button Command="{Binding LongRunningCommand}" /> 

のviewmodel:

ctor 
{ 
    LongRunningCommand = new DelegateCommand<object>(ProcessLongRunningCommand); 
} 

public DelegateCommand LongRunningCommand { get; private set; } 
private async void ProcessLongRunningCommand(object e) 
{ 
    await Task.Delay(5000); 
} 

しかし、実際の方法でTask.Delayを置き換えた場合、私のUI はフリーダイヤルです。これはとても奇妙です。例えば下記をご覧:

<Button Command="{Binding LongRunningCommand}" /> 

のviewmodel:

private readonly IDbAccess _dbAccess; 

ctor(IDbAccess dbAccess) 
{ 
    _dbAccess = dbAccess 
    LongRunningCommand = new DelegateCommand<object>(ProcessLongRunningCommand); 
} 

public DelegateCommand LongRunningCommand { get; private set; } 
private async void ProcessLongRunningCommand(object e) 
{ 
    var callResult = await _dbAccess.LongRunningMethod(); 

    //adjust viewmodel observablecollection property which binds to a ListBox with callResult 
} 

DBACCESSのIMPL:結合

XAML

public Task LongRunningMethod(object e) 
{ 
    return Task.Run(() => 
    { 
     ... 
    } 
} 

は誰かが、私が間違ってやって見せて下さい。私はこれで多くの時間を失った...

そしてbtw私はasync voidがベストプラクティスではないことを知っていますが、私はDelegateCommandを非同期にするソリューションを見つけることができませんでした。

EDIT

は、より多くの研究の後、私たちは、これは 'レンダリング' の問題であると結論づけました。 LongRunningCommandは非同期ですが、レンダリングとバインディングに時間がかかり、UIがブロックされます。私はこのレンダリングの問題を解決する方法を知らない。

+0

_adjust viewmodel observablecollectionがcallResult_でUIの更新をいくつかしている場合にフリーズする – Fabio

+0

observablecollectionに200個の結果を書き込むだけで、ウィンドウがブロックされます。私は窓を動かすことも傾けたり、1秒間リサイズしたりもしない。 – Ozkan

+2

[この記事はMSDNから](https://msdn.microsoft.com/en-gb/magazine/dn630647.aspx)を見ましたか? – XAMlMAX

答えて

2

解決策が見つかるまで、デッドロックを待っているこのタスクは、長い間私を捉えていました。

var callResult = await _dbAccess.LongRunningMethod().ConfigureAwait(false); 

var callResult = await _dbAccess.LongRunningMethod(); 

を交換理由の詳細についてはステファン・クリアリーによってthis blog postを参照してください。

awaitの後の継続は別のディスパッチャコンテキストになるため、UIを直接更新するもの(監視可能なコレクションの作成など)はUIディスパッチャにマーシャリングする必要があります。多くのMVVMフレームワークには、これを支援するユーティリティが含まれています。MVVM LightのDispatcherHelperクラスを使用しています。

Resharperを使用している場合は、プラグインをインストールして、すべてのawait文にConfigureAwait()が追加されていることを確認できます。

+0

OPはデッドロックについて言及していません。 – Fabio

+2

"しかし、私がTask.Delayを実際のメソッドに置き換えると、UIがフリーズする" ...まさにデッドロックの問題です。 – Peregrine

+0

これは問題のOPの解決策である可能性が最も高いです。私はconfigurewaitアナライザをプロジェクトに添付して使用します。それが私たちの行うことです。安全なコードを確保するためにVS拡張機能に依存するビルドチェーンを望んでいません – Dbl

関連する問題