[解決済み] Task.Runの正しい使い方とasync-awaitだけの使い方
質問
を使用する際の正しいアーキテクチャについてご意見を伺いたいと思います。
Task.Run
. WPF .NET 4.5でUIにラグが発生しています。
アプリケーション(Caliburn Microフレームワークを使用)でUIにラグが発生しています。
基本的に私は(非常に単純化されたコードスニペット)やっています。
public class PageViewModel : IHandle<SomeMessage>
{
...
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
// Makes UI very laggy, but still not dead
await this.contentLoader.LoadContentAsync();
HideLoadingAnimation();
}
}
public class ContentLoader
{
public async Task LoadContentAsync()
{
await DoCpuBoundWorkAsync();
await DoIoBoundWorkAsync();
await DoCpuBoundWorkAsync();
// I am not really sure what all I can consider as CPU bound as slowing down the UI
await DoSomeOtherWorkAsync();
}
}
私が読んだ/見た記事/ビデオからは
await
async
は必ずしもバックグラウンドスレッドで実行されているわけではなく、バックグラウンドで作業を開始するためには、awaitでラップする必要があります。
Task.Run(async () => ... )
. 使用方法
async
await
はUIをブロックしませんが、それでもUIスレッドで実行されているので、ラグが発生しています。
Task.Runはどこに置くのがベストでしょうか?
のみでよいのでしょうか?
-
外側の呼び出しをラップすることで、.NETのスレッド作業が少なくなるからです。
-
で実行されているCPUバウンドメソッドのみをラップすべきか、それとも
Task.Run
これによって、他の場所でも再利用できるようになるのでしょうか?コア深部のバックグラウンドスレッドで作業を開始するのが良いアイデアなのかどうか、ここではよくわかりません。
広告(1)、最初の解決策はこんな感じでしょうか。
public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
await Task.Run(async () => await this.contentLoader.LoadContentAsync());
HideLoadingAnimation();
}
// Other methods do not use Task.Run as everything regardless
// if I/O or CPU bound would now run in the background.
広告(2)の場合、2つ目の解答はこのようになります。
public async Task DoCpuBoundWorkAsync()
{
await Task.Run(() => {
// Do lot of work here
});
}
public async Task DoSomeOtherWorkAsync(
{
// I am not sure how to handle this methods -
// probably need to test one by one, if it is slowing down UI
}
解決方法は?
注意 UIスレッドで作業を行うためのガイドライン 私のブログで紹介しています。
- UIスレッドを一度に50ミリ秒以上ブロックしない。
- UIスレッドでの継続は1秒間に100回までとし、1000回はやりすぎです。
使うべきテクニックは2つあります。
1)使用する
ConfigureAwait(false)
は、できる限り
例)。
await MyAsync().ConfigureAwait(false);
の代わりに
await MyAsync();
.
ConfigureAwait(false)
は
await
は、現在のコンテキストで再開する必要がないことを示します(この場合、"現在のコンテキストで"とは、"UIスレッドで"を意味します)。しかし、その残りの部分については
async
メソッドの後(
ConfigureAwait
) では、現在のコンテキストにいることを前提とした操作 (例: UI 要素の更新) ができない。
詳細については、私のMSDN記事 非同期プログラミングのベストプラクティス .
2)使用する
Task.Run
を使用して、CPUバウンドメソッドを呼び出します。
を使用する必要があります。
Task.Run
しかし、再利用したいコード(つまり、ライブラリコード)内では使わないでください。そこで、あなたは
Task.Run
から
コール
の一部ではなく、メソッドになります。
実装
を指定します。
つまり、純粋なCPU縛りの仕事はこんな感じでしょうか。
// Documentation: This method is CPU-bound.
void DoWork();
を使用して呼び出します。
Task.Run
:
await Task.Run(() => DoWork());
となるメソッド。
混合物
には、CPUバウンドとI/Oバウンドに対応した
Async
という署名があり、CPUバウンドであることを示す文書があります。
// Documentation: This method is CPU-bound.
Task DoWorkAsync();
を使用して呼び出すこともできます。
Task.Run
(部分的にCPUバウンドするため)。
await Task.Run(() => DoWorkAsync());
関連
-
[解決済み] 保護レベルによりアクセス不能になりました。
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み] forEachループでasync/awaitを使用する
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] async」と「await」の使い方とタイミング
-
[解決済み] async/await関数を並列に呼び出す
-
[解決済み] async/await - タスクとvoidをいつ返すか?
-
[解決済み] Task.Runをメソッドに入れないと非同期にはならないのですか?
-
[解決済み】非同期プログラミングとマルチスレッドの違いは何ですか?
-
[解決済み】非同期処理の待ち時間、Wait()でプログラムがフリーズする原因はここにある
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】"出力タイプがクラスライブラリのプロジェクトは直接起動できない"
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】C#はJavaのcharAt()と同等?)
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み] UnityでOnCollisionEnterが呼ばれない
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み】同期接続にHttpClientを使用する理由