質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

7241閲覧

C# async/await Result 使い方

fia

総合スコア57

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2020/09/18 15:35

質問

非同期処理の基本的な考え方の話なのですが、asyncメソッドを使用した時のawaitとResultの違いは両方処理が終わるのは待つがメインスレッドが止まるか止まらないかの違いということでよいのですか。

C#

1async void hoge(){ 2 string s=await fuga(); 3}

C#

1void hoge(){ 2 string s=fuga().Result; 3}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gentaro

2020/09/18 17:41

そもそも下は非同期処理じゃないのですが、質問したいポイントはどこですか? 非同期処理とは何か?を聞きたいんですか?
退会済みユーザー

退会済みユーザー

2020/09/19 00:05 編集

色々情報不足です。以下を質問欄を編集して追記してください。 何を作っているか書きましょう。コンソールアプリと Windows Forms では話が違ってきます。時にあなたが気にしている「メインスレッドが止まるか止まらないか」というところ。 fuga の中身を書いてください。 開発環境を書いてください。
guest

回答1

0

ベストアンサー

質問への私のコメント、

何を作っているか書きましょう。コンソールアプリと Windows Forms では話が違ってきます。時にあなたが気にしている「メインスレッドが止まるか止まらないか」というところ。

fuga の中身を書いてください。

・・・に返事がないのではっきりしませんが、「メインスレッドが止まるか止まらないか」を気にしているということは多分 Windows Forms のような GUI アプリで、fuga は Task<string> を返す以下のようなメソッドであろうと想像してレスします。

private async Task<string> fuga() { await Task.Delay(3000); return "戻り値"; }

asyncメソッドを使用した時のawaitとResultの違いは両方処理が終わるのは待つがメインスレッドが止まるか止まらないかの違いということでよいのですか。

前者の async / await を使った方は await で fuga の処理が終わるのを待ちますがメッセージループは処理されるので GUI はフリーズしません。それはたぶん質問者さんが期待する動きになると思います。

しかし、質問者さんのコードの後者の Task.Result を使った方はデッドロックになると思います。

「思います」と言うだけでは説得力がないので、Windows Forms アプリで以下のコードを書いて検証してみました。コメントにデッドロックと書いた方(質問者さんの例では後者の方)はデッドロックになります。

using System; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsAsyncTest { public partial class Form3 : Form { public Form3() { InitializeComponent(); } // デッドロック // Task.Result プロパティの get アクセサーにアクセスすると // 非同期操作が完了するまで呼び出し元のスレッドがブロックされる。 // これは、Wait メソッドを呼び出すことと同じ private void button1_Click(object sender, EventArgs e) { label1.Text = ""; string str = TimeCosumingMethod().Result; label1.Text = str; } // 正常動作 private async void button2_Click(object sender, EventArgs e) { label1.Text = ""; string str = await TimeCosumingMethod(); label1.Text = str; } private async Task<string> TimeCosumingMethod() { await Task.Delay(3000); return "TimeCosumingMethod の戻り値"; } } }

その理由については以下の記事の「図 3 非同期コードをブロックする際によくあるデッドロックの問題」のセクションが参考になると思います。

非同期プログラミングのベスト プラクティス
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

ちなみに、上の記事に書いてある通り、コンソールアプリであればデッドロックにはなりません。以下のコードで確認しました。

using System; using System.Threading.Tasks; using System.Threading; namespace ConsoleAppAsync3 { class Program { static async Task Main(string[] args) { Console.WriteLine("Main のはじまり " + Thread.CurrentThread.ManagedThreadId); string str1 = await TimeCosumingMethod(); Console.WriteLine(str1); string str2 = TimeCosumingMethod().Result; Console.WriteLine(str2); Console.WriteLine("Main のおわり " + Thread.CurrentThread.ManagedThreadId); } static async Task<string> TimeCosumingMethod() { Console.WriteLine("TimeCosumingMethod はじまり " + Thread.CurrentThread.ManagedThreadId); await Task.Delay(3000); Console.WriteLine("TimeCosumingMethod おわり " + Thread.CurrentThread.ManagedThreadId); return "TimeCosumingMethod の戻り値 " + Thread.CurrentThread.ManagedThreadId; } } }

結果は:

イメージ説明

投稿2020/09/19 04:20

編集2020/09/19 07:40
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fia

2020/09/19 09:05

GUIやCUIで非同期処理を書くことが多々あり曖昧なまま書いていたため質問致しました。 両方のケースのコードを書いていただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問